2014-11-04 00:28:28 +00:00
require 'faraday'
require 'launchy'
require 'cgi'
require 'json'
require 'google/api_client'
require 'google/api_client/client_secrets'
require 'google/api_client/auth/installed_app'
2017-04-14 19:34:18 +00:00
require 'socket'
#Google::Apis.logger.level = Logger::DEBUG
YOUTUBE_API_SERVICE_NAME = 'youtube'
YOUTUBE_API_VERSION = 'v3'
2015-01-01 01:35:20 +00:00
# Youtube OAuth and API functionality:
2014-11-04 00:28:28 +00:00
module JamRuby
2015-01-11 23:04:16 +00:00
class GoogleClient
2014-11-04 00:28:28 +00:00
attr_accessor :client
2017-04-14 19:34:18 +00:00
attr_accessor :api
2014-11-04 00:28:28 +00:00
attr_accessor :request
attr_accessor :server
attr_accessor :socket
attr_accessor :config
attr_accessor :redirect_uri
def initialize ( )
self . config = Rails . application . config
self . redirect_uri = 'http://localhost:2112/auth/google_login/callback'
self . client = Google :: APIClient . new (
2017-04-14 19:34:18 +00:00
:application_name = > 'JamKazam' ,
:application_version = > '1.0.0'
2014-11-04 00:28:28 +00:00
)
end
2017-04-14 19:34:18 +00:00
def youtube
@youtube || = client . discovered_api ( 'youtube' , 'v3' )
end
def create_authorization ( user_auth , scope , autorefresh )
authorization = Signet :: OAuth2 :: Client . new (
:authorization_uri = > " https://accounts.google.com/o/oauth2/auth " ,
:token_credential_uri = > " https://accounts.google.com/o/oauth2/token " ,
:client_id = > @config . google_client_id ,
:client_secret = > @config . google_secret ,
#:redirect_uri => credentials.redirect_uris.first,
:scope = > scope
)
authorization . access_token = user_auth . token
authorization . refresh_token = user_auth . refresh_token
authorization . expires_at = user_auth . token_expiration
if autorefresh && ( user_auth . token_expiration < ( Time . now - 15 ) ) # add 15 second buffer to this time, because OAUth server does not respond with timestamp, but 'expires_in' which is just offset seconds
# XXX: what to do when this fails?
authorization . refresh!
user_auth . token = authorization . access_token
user_auth . token_expiration = authorization . issued_at + authorization . expires_in
user_auth . save
end
authorization
end
def create_client
Google :: APIClient . new (
:application_name = > 'JamKazam' ,
:application_version = > '1.0.0' ,
)
end
2014-11-04 00:28:28 +00:00
# Return a login URL that will show a web page with
def get_login_url ( username = nil )
2017-04-14 19:34:18 +00:00
puts " GET LOGIN URL "
2014-11-04 00:28:28 +00:00
uri = " https://accounts.google.com/o/oauth2/auth "
2017-04-14 19:34:18 +00:00
uri << " ?scope= #{ CGI . escape ( 'https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.upload https://www.googleapis.com/auth/youtube https://gdata.youtube.com email profile ' ) } " # # https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.upload
2014-11-04 00:28:28 +00:00
uri << " &client_id= #{ CGI . escape ( self . config . google_email ) } "
uri << " &response_type=code "
uri << " &access_type=online "
uri << " &prompt=consent "
uri << " &state=4242 "
uri << " &redirect_uri= #{ redirect_uri } "
if username . present?
uri << " &login_hint= #{ ( username ) } "
end
uri
end
2017-04-14 19:34:18 +00:00
# create youtube broadcast
def create_broadcast ( user , broadcast_options )
auth = UserAuthorization . google_auth ( user ) . first
if auth . nil? || auth . token . nil?
raise JamPermissionError , " No current google token found for user #{ user } "
end
broadcast_data = {
" snippet " = > broadcast_options [ :snippet ] ,
" status " = > broadcast_options [ :status ] ,
" contentDetails " = > broadcast_options [ :contentDetails ]
}
begin
#secrets = Google::APIClient::ClientSecrets.new({"web" => {"access_token" => auth.token, "refresh_token" => auth.refresh_token, "client_id" => @config.google_client_id, "client_secret" => @config.google_secret}})
my_client = create_client
my_client . authorization = create_authorization ( auth , 'https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.force-ssl' , true )
puts " BROADCAST DATA: #{ broadcast_data } "
#y = my_client.discovered_api('youtube', 'v3')
response = my_client . execute! ( :api_method = > youtube . live_broadcasts . insert ,
:parameters = > { :part = > 'contentDetails,status,snippet' } ,
:body_object = > broadcast_data )
body = JSON . parse ( response . body )
puts " CREATE BROADCAST RESPONSE: #{ body } "
return body
rescue Google :: APIClient :: ClientError = > e
# ex:
= begin
ex = {
" error " : {
" errors " : [
{
" domain " : " youtube.liveBroadcast " ,
" reason " : " liveStreamingNotEnabled " ,
" message " : " The user is not enabled for live streaming. " ,
" extendedHelp " : " https://www.youtube.com/features "
}
] ,
" code " : 403 ,
" message " : " The user is not enabled for live streaming. "
}
}
ex = {
" error " : {
" errors " : [
{
" domain " : " youtube.liveBroadcast " ,
" reason " : " insufficientLivePermissions " ,
" message " : " Request is not authorized " ,
" extendedHelp " : " https://developers.google.com/youtube/v3/live/docs/liveBroadcasts/insert # auth_required "
}
] ,
" code " : 403 ,
" message " : " Request is not authorized "
}
}
= end
puts e . result . body
raise e
end
end
def bind_broadcast ( user , broadcast_id , stream_id )
auth = UserAuthorization . google_auth ( user ) . first
if auth . nil? || auth . token . nil?
raise JamPermissionError , " No current google token found for user #{ user } "
end
begin
my_client = create_client
my_client . authorization = create_authorization ( auth , 'https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.force-ssl' , true )
#y = my_client.discovered_api('youtube', 'v3')
response = my_client . execute! ( :api_method = > youtube . live_broadcasts . bind ,
:parameters = > { :part = > 'id,contentDetails,status,snippet' , :id = > broadcast_id , :streamId = > stream_id } )
body = JSON . parse ( response . body )
puts " BIND RESPONSE: #{ body } "
return body
rescue Google :: APIClient :: ClientError = > e
puts e . result . body
raise e
end
end
2017-06-10 20:34:08 +00:00
def transition_broadcast ( user , broadcast_id , broadcastStatus )
auth = UserAuthorization . google_auth ( user ) . first
if auth . nil? || auth . token . nil?
raise JamPermissionError , " No current google token found for user #{ user } "
end
begin
my_client = create_client
my_client . authorization = create_authorization ( auth , 'https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.force-ssl' , true )
#y = my_client.discovered_api('youtube', 'v3')
response = my_client . execute! ( :api_method = > youtube . live_broadcasts . transition ,
:parameters = > { :part = > 'id,contentDetails,status,snippet' , :id = > broadcast_id , :broadcastStatus = > broadcastStatus } )
body = JSON . parse ( response . body )
puts " TRANSITION RESPONSE: #{ body } "
return body
rescue Google :: APIClient :: ClientError = > e
puts e . result . body
raise e
end
end
2017-04-14 19:34:18 +00:00
def get_broadcast ( user , broadcast_id )
auth = UserAuthorization . google_auth ( user ) . first
if auth . nil? || auth . token . nil?
raise JamPermissionError , " No current google token found for user #{ user } "
end
begin
my_client = create_client
my_client . authorization = create_authorization ( auth , 'https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.force-ssl' , true )
#y = my_client.discovered_api('youtube', 'v3')
response = my_client . execute! ( :api_method = > youtube . live_broadcasts . list ,
:parameters = > { :part = > 'id,contentDetails,status,snippet' , :id = > broadcast_id } )
body = JSON . parse ( response . body )
2017-06-10 20:34:08 +00:00
puts " GET BROADCAST RESPONSE: #{ body } "
if body [ " items " ] . length == 0
nil
else
body [ " items " ] [ 0 ] # returns array of items. meh
end
rescue Google :: APIClient :: ClientError = > e
puts e . result . body
raise e
end
end
def get_livestream ( user , stream_id )
auth = UserAuthorization . google_auth ( user ) . first
if auth . nil? || auth . token . nil?
raise JamPermissionError , " No current google token found for user #{ user } "
end
begin
my_client = create_client
my_client . authorization = create_authorization ( auth , 'https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.force-ssl' , true )
#y = my_client.discovered_api('youtube', 'v3')
response = my_client . execute! ( :api_method = > youtube . live_streams . list ,
:parameters = > { :part = > 'id,snippet,cdn,status' , :id = > stream_id } )
body = JSON . parse ( response . body )
puts " GET LIVE STREAM RESPONSE: #{ body } "
if body [ " items " ] . length == 0
nil
else
body [ " items " ] [ 0 ] # returns array of items. meh
end
2017-04-14 19:34:18 +00:00
rescue Google :: APIClient :: ClientError = > e
puts e . result . body
raise e
end
end
def create_stream ( user , stream_options )
auth = UserAuthorization . google_auth ( user ) . first
if auth . nil? || auth . token . nil?
raise JamPermissionError , " No current google token found for user #{ user } "
end
broadcast_data = {
" snippet " = > stream_options [ :snippet ] ,
" cdn " = > stream_options [ :cdn ] ,
" contentDetails " = > stream_options [ :contentDetails ]
}
begin
my_client = create_client
my_client . authorization = create_authorization ( auth , 'https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.force-ssl' , true )
puts " STREAM DATA: #{ broadcast_data } "
#y = my_client.discovered_api('youtube', 'v3')
response = my_client . execute! ( :api_method = > youtube . live_streams . insert ,
:parameters = > { :part = > 'id,contentDetails,cdn,status,snippet' } ,
:body_object = > broadcast_data )
body = JSON . parse ( response . body )
puts " CREATE STREAM RESPONSE: #{ body } "
return body
rescue Google :: APIClient :: ClientError = > e
puts e . result . body
raise e
end
end
# create youtube broadcast
def update_broadcast ( user , broadcast_options )
end
2014-11-04 00:28:28 +00:00
# Contacts youtube and prepares an upload to youtube. This
# process is somewhat painful, even in ruby, so we do the preparation
# and the client does the actual upload using the URL returned:
# https://developers.google.com/youtube/v3/docs/videos/insert
# https://developers.google.com/youtube/v3/guides/using_resumable_upload_protocol
2017-04-14 19:34:18 +00:00
def sign_youtube_upload ( user , filename , length )
2014-11-04 00:28:28 +00:00
raise ArgumentError , " Length is required and should be > 0 " if length . to_i . zero?
2017-04-14 19:34:18 +00:00
2014-11-04 00:28:28 +00:00
# Something like this:
# POST /upload/youtube/v3/videos?uploadType=resumable&part=snippet,status,contentDetails HTTP/1.1
# Host: www.googleapis.com
# Authorization: Bearer AUTH_TOKEN
# Content-Length: 278
# Content-Type: application/json; charset=UTF-8
# X-Upload-Content-Length: 3000000
# X-Upload-Content-Type: video/*
# {
# "snippet": {
# "title": "My video title",
# "description": "This is a description of my video",
# "tags": ["cool", "video", "more keywords"],
# "categoryId": 22
# },
# "status": {
# "privacyStatus": "public",
# "embeddable": True,
# "license": "youtube"
# }
# }
auth = UserAuthorization . google_auth ( user ) . first
if auth . nil? || auth . token . nil?
2017-04-14 19:34:18 +00:00
raise SecurityError , " No current google token found for user #{ user } "
2014-11-04 00:28:28 +00:00
end
video_data = {
2017-04-14 19:34:18 +00:00
" snippet " = > {
" title " = > filename ,
" description " = > filename ,
" tags " = > [ " cool " , " video " , " more keywords " ] ,
" categoryId " = > 1
} ,
" status " = > {
" privacyStatus " = > " public " ,
" embeddable " = > true ,
" license " = > " youtube "
}
}
conn = Faraday . new ( :url = > " https://www.googleapis.com " , :ssl = > { :verify = > false } ) do | faraday |
faraday . request :url_encoded
faraday . adapter Faraday . default_adapter
2014-11-04 00:28:28 +00:00
end
video_json = video_data . to_json
result = conn . post ( " /upload/youtube/v3/videos?access_token= #{ CGI . escape ( auth . token ) } &uploadType=resumable&part=snippet,status,contentDetails " ,
2017-04-14 19:34:18 +00:00
video_json ,
{
'content-type' = > 'application/json;charset=utf-8' ,
'x-Upload-Content-Length' = > " #{ length } " ,
'x-upload-content-type' = > " video/* "
}
2014-11-04 00:28:28 +00:00
)
2017-04-14 19:34:18 +00:00
2014-11-04 00:28:28 +00:00
# Response should something look like:
2015-01-01 01:35:20 +00:00
# HTTP/1.1 200 OK
# Location: https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&upload_id=xa298sd_f&part=snippet,status,contentDetails
# Content-Length: 0
2014-11-04 00:28:28 +00:00
if ( result . nil? || result . status! = 200 || result . headers [ 'location' ] . blank? )
msg = " Failed signing with status= #{ result . status } #{ result . inspect } : "
if result . body . present? && result . body . length > 2
2017-04-14 19:34:18 +00:00
msg << result . body . inspect # JSON.parse(result.body).inspect
2014-11-04 00:28:28 +00:00
end
# TODO: how to test for this:
# If reason is "youtubeSignupRequired"
# If the user's youtube account is unlinked, they'll have to go here.
# http://m.youtube.com/create_channel. With v3, there is no automated way to do this.
raise msg
else
# This has everything one needs to start the upload to youtube:
{
2017-04-14 19:34:18 +00:00
" method " = > " PUT " ,
" url " = > result . headers [ 'location' ] ,
" Authorization " = > " Bearer #{ auth . token } " ,
" Content-Length " = > length ,
" Content-Type " = > " video/* "
}
2014-11-04 00:28:28 +00:00
end
2017-04-14 19:34:18 +00:00
end
2014-11-04 00:28:28 +00:00
# https://developers.google.com/youtube/v3/guides/using_resumable_upload_protocol#Check_Upload_Status
2015-01-11 23:04:16 +00:00
def youtube_upload_status ( user , upload_url , length )
2014-11-04 00:28:28 +00:00
auth = UserAuthorization . google_auth ( user ) . first
if auth . nil? || auth . token . nil?
2017-04-14 19:34:18 +00:00
raise SecurityError , " No current google token found for user #{ user } "
2014-11-04 00:28:28 +00:00
end
# PUT UPLOAD_URL HTTP/1.1
# Authorization: Bearer AUTH_TOKEN
# Content-Length: 0
# Content-Range: bytes */CONTENT_LENGTH
RestClient . put ( upload_url , nil , {
2017-04-14 19:34:18 +00:00
'Authorization' = > " Bearer #{ auth . token } " ,
'Content-Length' = > " 0 " ,
'Content-Range' = > " bytes */ #{ length } "
} ) do | response , request , result |
2014-11-04 00:28:28 +00:00
# Result looks like this:
# 308 Resume Incomplete
# Content-Length: 0
# Range: bytes=0-999999
2017-04-14 19:34:18 +00:00
case ( response . code )
2014-11-04 00:28:28 +00:00
when 200 .. 207
result_hash = {
2017-04-14 19:34:18 +00:00
" offset " = > 0 ,
" length " = > length ,
" status " = > response . code
2014-11-04 00:28:28 +00:00
}
when 308
range_str = response . headers [ 'Range' ]
if range_str . nil?
range = 0 .. length
else
range = range_str . split ( " - " )
end
result_hash = {
2017-04-14 19:34:18 +00:00
" offset " = > range . first . to_i ,
" length " = > range . last . to_i ,
" status " = > response . code
2014-11-04 00:28:28 +00:00
}
else
raise " Unexpected status from youtube: [ #{ response . code } ] with headers: #{ response . headers . inspect } "
2017-04-14 19:34:18 +00:00
end
2014-11-04 00:28:28 +00:00
2017-04-14 19:34:18 +00:00
result_hash
2014-11-04 00:28:28 +00:00
end
end
# @return true if file specified by URL uploaded, false otherwise
2015-01-11 23:04:16 +00:00
def verify_youtube_upload ( user , upload_url , length )
status_hash = youtube_upload_status ( user , upload_url , length )
2014-11-04 00:28:28 +00:00
( status_hash [ 'status' ] > = 200 && status_hash [ 'status' ] < 300 )
2017-04-14 19:34:18 +00:00
end
2014-11-04 00:28:28 +00:00
2015-01-01 01:35:20 +00:00
# Set fully_uploaded if the upload can be verified.
# @return true if verified; false otherwise:
2017-04-14 19:34:18 +00:00
def complete_upload ( recorded_video )
2015-01-11 23:04:16 +00:00
if ( verify_youtube_upload ( recorded_video . user , recorded_video . url , recorded_video . length ) )
2014-11-04 00:28:28 +00:00
recorded_video . update_attribute ( :fully_uploaded , true )
2017-04-14 19:34:18 +00:00
else
2014-11-04 00:28:28 +00:00
false
end
end
2015-01-11 23:04:16 +00:00
def verify_recaptcha ( recaptcha_response )
success = false
if ! Rails . application . config . recaptcha_enable
2017-04-14 19:34:18 +00:00
success = true
2015-01-11 23:04:16 +00:00
else
Rails . logger . info " Login with: #{ recaptcha_response } "
2017-04-14 19:34:18 +00:00
RestClient . get ( " https://www.google.com/recaptcha/api/siteverify " ,
params : {
secret : Rails . application . config . recaptcha_private_key ,
response : recaptcha_response
}
2015-01-11 23:04:16 +00:00
) do | response , request , result |
Rails . logger . info " response: #{ response . inspect } "
2017-04-14 19:34:18 +00:00
case ( response . code )
2015-01-11 23:04:16 +00:00
when 200 .. 207
json = JSON . parse ( response . to_str )
if json [ 'success' ]
success = true
else
Rails . logger . info ( " Error verifying recaptcha: #{ json [ 'error-codes' ] . inspect } " )
end
else
Rails . logger . info ( " Unexpected status from google_recaptcha: [ #{ response . code } ] with headers: #{ response . headers . inspect } " )
end #case
end #do
end # if
success
2017-04-14 19:34:18 +00:00
end
#def
2015-01-11 23:04:16 +00:00
2014-11-04 00:28:28 +00:00
# This will also sign in and prompt for login as necessary;
# currently requires the server to be running at localhost:3000
2017-04-14 19:34:18 +00:00
def signin_flow ( )
2014-11-04 00:28:28 +00:00
config = Rails . application . config
self . client = Google :: APIClient . new (
2017-04-14 19:34:18 +00:00
:application_name = > 'JamKazam' ,
:application_version = > '1.0.0'
2014-11-04 00:28:28 +00:00
)
2017-04-14 19:34:18 +00:00
raise " SIGNIN FLOW!! "
2014-11-04 00:28:28 +00:00
flow = Google :: APIClient :: InstalledAppFlow . new (
2017-04-14 19:34:18 +00:00
:client_id = > config . google_client_id ,
:client_secret = > config . google_secret ,
:redirect_uri = > redirect_uri ,
:scope = > 'email profile https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.upload'
2014-11-04 00:28:28 +00:00
)
self . client . authorization = flow . authorize
end
# Must manually confirm to obtain refresh token:
2017-04-14 19:34:18 +00:00
def get_refresh_token
2014-11-04 00:28:28 +00:00
config = Rails . application . config
2017-04-14 19:34:18 +00:00
conn = Faraday . new ( :url = > 'https://accounts.google.com' , :ssl = > { :verify = > false } ) do | faraday |
faraday . request :url_encoded
faraday . adapter Faraday . default_adapter
2014-11-04 00:28:28 +00:00
end
wait_for_callback do | refresh_token |
Rails . logger . info ( " The refresh_token is #{ refresh_token } " )
end
result = conn . get '/o/oauth2/auth' , {
2017-04-14 19:34:18 +00:00
'scope' = > 'email profile https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.upload' ,
'client_id' = > config . google_client_id ,
'response_type' = > " code " ,
'access_type' = > " offline " ,
'redirect_uri' = > redirect_uri
}
2014-11-04 00:28:28 +00:00
end
2017-04-14 19:34:18 +00:00
def get_access_token ( refresh_token )
2014-11-04 00:28:28 +00:00
refresh_token = " 4/g9uZ8S4lq2Bj1J8PPIkgOFKhTKmCHSmRe68iHA75hRg.gj8Nt5bpVYQdPm8kb2vw2M23tnRnkgI "
2017-04-14 19:34:18 +00:00
2014-11-04 00:28:28 +00:00
config = Rails . application . config
2017-04-14 19:34:18 +00:00
conn = Faraday . new ( :url = > 'https://accounts.google.com' , :ssl = > { :verify = > false } ) do | faraday |
faraday . request :url_encoded
faraday . adapter Faraday . default_adapter
2014-11-04 00:28:28 +00:00
end
wait_for_callback do | access_token |
2017-04-14 19:34:18 +00:00
Rails . logger . info ( " The access_token is #{ access_token } " )
2014-11-04 00:28:28 +00:00
end
result = conn . post '/o/oauth2/token' , nil , {
2017-04-14 19:34:18 +00:00
'scope' = > 'email profile https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.upload' ,
'client_id' = > config . google_client_id ,
'client_secret' = > config . google_secret ,
'refresh_token' = > refresh_token ,
'grant_type' = > " refresh_token " ,
'redirect_uri' = > redirect_uri
}
2014-11-04 00:28:28 +00:00
Rails . logger . info ( " REsult: #{ result . inspect } \n \n " )
end
2017-04-14 19:34:18 +00:00
def wait_for_callback ( port = 3000 )
2014-11-04 00:28:28 +00:00
shutdown ( )
self . server = Thread . new {
Rails . logger . info ( " STARTING SERVER THREAD... " )
tcp_server = TCPServer . new ( 'localhost' , port )
self . socket = tcp_server . accept
if self . socket
request = self . socket . gets
Rails . logger . info ( " REQUEST: #{ request } " )
2017-04-14 19:34:18 +00:00
2014-11-04 00:28:28 +00:00
params = CGI . parse ( request )
code = params [ 'code' ] . first
# Whack the end part:
access_code = code ? code . split ( " " ) . first : " "
status = ( access_code . present? ) ? 'OK' : 'EMPTY'
Rails . logger . info ( " access_code is #{ status } " )
token = exchange_for_token ( access_code )
yield ( token )
2017-04-14 19:34:18 +00:00
response = " #{ status } \n "
2014-11-04 00:28:28 +00:00
self . socket . print " HTTP/1.1 200 OK \r \n " +
2017-04-14 19:34:18 +00:00
" Content-Type: text/plain \r \n " +
" Content-Length: #{ response . bytesize } \r \n " +
" Connection: close \r \n "
2014-11-04 00:28:28 +00:00
self . socket . print " \r \n "
self . socket . print response
2017-04-14 19:34:18 +00:00
self . socket . close
2015-07-20 12:58:15 +00:00
self . socket = nil
2015-07-19 14:57:40 +00:00
else
puts " WHY WOULD THIS EVER HAPPEN? "
raise " WHY WOULD THIS EVER HAPPEN? "
2014-11-04 00:28:28 +00:00
end
2015-07-19 14:57:40 +00:00
2014-11-04 00:28:28 +00:00
}
end
def exchange_for_token ( access_code )
2015-01-01 01:35:20 +00:00
Rails . logger . info ( " Exchanging token for code: [ #{ access_code } ] " )
2017-04-14 19:34:18 +00:00
conn = Faraday . new ( :url = > " https://accounts.google.com " , :ssl = > { :verify = > false } ) do | faraday |
faraday . request :url_encoded
faraday . adapter Faraday . default_adapter
2014-11-04 00:28:28 +00:00
end
exchange_parms = {
2017-04-14 19:34:18 +00:00
'grant_type' = > 'authorization_code' ,
'code' = > ( access_code ) ,
'client_id' = > ( config . google_email ) ,
'client_secret' = > ( config . google_secret ) ,
'redirect_uri' = > ( redirect_uri ) ,
2014-11-04 00:28:28 +00:00
}
result = conn . post ( '/o/oauth2/token' , exchange_parms )
if result . body . nil? || result . body . blank?
raise " Result not in correct form: [ #{ result . body } ] "
end
body_hash = JSON . parse ( result . body )
body_hash [ 'access_token' ]
end
# shutdown
2017-04-14 19:34:18 +00:00
def shutdown ( )
2014-11-04 00:28:28 +00:00
Rails . logger . info ( " Stopping oauth server... " )
if ( self . socket )
begin
self . socket . close
rescue IOError
# Expected for most cases:
Rails . logger . info ( " Socket already closed. " )
end
self . socket = nil
end
end
end # class
end # module