rgigya 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +13 -5
- data/VERSION +1 -1
- data/lib/rgigya/base.rb +340 -0
- data/lib/rgigya/hash.rb +19 -0
- data/lib/rgigya/sig_utils.rb +98 -0
- data/lib/rgigya.rb +3 -193
- data/rgigya.gemspec +8 -3
- data/spec/helpers.rb +26 -0
- data/spec/rgigya_secure_spec.rb +18 -0
- data/spec/rgigya_shared_examples.rb +315 -0
- data/spec/rgigya_signature_spec.rb +62 -0
- data/spec/spec_helper.rb +4 -5
- data/test/dummy/Gemfile +0 -1
- data/test/dummy/Gemfile.lock +8 -9
- data/test/dummy/config/environments/development.rb +6 -2
- data/test/dummy/log/development.log +300 -0
- metadata +21 -16
- data/spec/rgigya_spec.rb +0 -310
data/README.rdoc
CHANGED
@@ -23,8 +23,12 @@ You will need to setup your own dev site on the gigya platform for testing.
|
|
23
23
|
|
24
24
|
require 'RGigya'
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
RGigya.config({
|
27
|
+
:api_key => "<add api key here>",
|
28
|
+
:api_secret => "<add api secret here>",
|
29
|
+
:use_ssl => false,
|
30
|
+
:domain => "us1"
|
31
|
+
})
|
28
32
|
|
29
33
|
RGigya.socialize_notifyLogin({:siteUID => '1'})
|
30
34
|
|
@@ -34,8 +38,12 @@ You will need to setup your own dev site on the gigya platform for testing.
|
|
34
38
|
Edit your config/environments/development.rb file and add the following constants
|
35
39
|
|
36
40
|
|
37
|
-
|
38
|
-
|
41
|
+
RGigya.config({
|
42
|
+
:api_key => "<add api key here>",
|
43
|
+
:api_secret => "<add api secret here>",
|
44
|
+
:use_ssl => false,
|
45
|
+
:domain => "us1"
|
46
|
+
})
|
39
47
|
|
40
48
|
Then add your api calls in your controllers, models, libraries, etc.
|
41
49
|
|
@@ -90,7 +98,7 @@ Edit spec/spec_helper.rb
|
|
90
98
|
=== Running tests
|
91
99
|
|
92
100
|
cd <root of the project>
|
93
|
-
rspec
|
101
|
+
rspec
|
94
102
|
|
95
103
|
|
96
104
|
== Rails dummy site
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0
|
1
|
+
1.1.0
|
data/lib/rgigya/base.rb
ADDED
@@ -0,0 +1,340 @@
|
|
1
|
+
#
|
2
|
+
# Quick sdk for the gigya api
|
3
|
+
#
|
4
|
+
# You can reference api calls at http://developers.gigya.com/037_API_reference
|
5
|
+
#
|
6
|
+
# Example call
|
7
|
+
# RGigya.socialize_setStatus(:uid => @user.id,:status => 'hello')
|
8
|
+
#
|
9
|
+
# We split the method name by the underscore and then map
|
10
|
+
# the first token to the correct url
|
11
|
+
# The example above calls the url https://socialize.gigya.com/socialize.setStatus
|
12
|
+
#
|
13
|
+
# @author Scott Sampson
|
14
|
+
# @author Michael Orr
|
15
|
+
|
16
|
+
|
17
|
+
#
|
18
|
+
# Constants to be used for the gigya key and secret.
|
19
|
+
# These should be commented out and set in your environments for your rails project.
|
20
|
+
# Uncomment below for testing without rails
|
21
|
+
#
|
22
|
+
# RGigya.config({
|
23
|
+
# :api_key => "12345",
|
24
|
+
# :api_secret => "12345,
|
25
|
+
# :use_ssl => false,
|
26
|
+
# :domain => "us1"
|
27
|
+
# })
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
module RGigya
|
32
|
+
|
33
|
+
# List of Available API methods
|
34
|
+
@@valid_methods = [:socialize, :gm, :comments, :accounts, :reports, :chat, :ds]
|
35
|
+
|
36
|
+
# Used to compare when we get a bad signature, mainly for debugging but helpful
|
37
|
+
@@base_signature_string = ""
|
38
|
+
@@signature = ""
|
39
|
+
|
40
|
+
#
|
41
|
+
# Custom Exceptions so we know it came from the library
|
42
|
+
# When in use please namespace them appropriately RGigya::ResponseError for readability
|
43
|
+
#
|
44
|
+
exceptions = %w[ UIDParamIsNil SiteUIDParamIsNil ResponseError BadParamsOrMethodName ErrorCodeReturned MissingApiKey MissingApiSecret]
|
45
|
+
exceptions.each { |e| const_set(e, Class.new(StandardError)) }
|
46
|
+
RGigya::JSONParseError = Class.new(JSON::ParserError)
|
47
|
+
|
48
|
+
class << self
|
49
|
+
|
50
|
+
|
51
|
+
#
|
52
|
+
# Sets the config data to be used in the api call
|
53
|
+
#
|
54
|
+
# @param [Hash] config_dat Hash of key value pairs passed to the gigya api
|
55
|
+
#
|
56
|
+
# @author Scott Sampson
|
57
|
+
def config(config_data)
|
58
|
+
@@api_key = config_data[:api_key]
|
59
|
+
@@api_secret = config_data[:api_secret]
|
60
|
+
@@use_ssl = config_data[:use_ssl] || false
|
61
|
+
@@domain = config_data[:domain] || "us1"
|
62
|
+
|
63
|
+
verify_config_data
|
64
|
+
end
|
65
|
+
|
66
|
+
# Validates that we have required config data
|
67
|
+
#
|
68
|
+
# @author Scott Sampson
|
69
|
+
def verify_config_data
|
70
|
+
if(!defined?(@@api_key))
|
71
|
+
raise RGigya::MissingApiKey, "Please provide a Gigya api key in the config data"
|
72
|
+
end
|
73
|
+
if(!defined?(@@api_secret))
|
74
|
+
raise RGigya::MissingApiSecret, "Please provide a Gigya api secret in the config data"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# Adds the required params for all api calls
|
80
|
+
#
|
81
|
+
def required_parameters
|
82
|
+
params = "apiKey=#{CGI.escape(@@api_key)}"
|
83
|
+
params += "&secret=#{CGI.escape(@@api_secret)}"
|
84
|
+
params += "&format=json"
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# builds the url to be sent to the api
|
89
|
+
#
|
90
|
+
# @param [String] method The method name to be called in the gigya api
|
91
|
+
# @param [Hash] options Hash of key value pairs passed to the gigya api
|
92
|
+
#
|
93
|
+
# @return [String] the full url to be sent to the api
|
94
|
+
#
|
95
|
+
# @author Scott Sampson
|
96
|
+
def build_url(method, http_method, options = {})
|
97
|
+
if options && options.has_key?(:uid) && options[:uid].nil?
|
98
|
+
raise RGigya::UIDParamIsNil, ""
|
99
|
+
end
|
100
|
+
|
101
|
+
if options && options.has_key?(:siteUID) && options[:siteUID].nil?
|
102
|
+
raise RGigya::SiteUIDParamIsNil, ""
|
103
|
+
end
|
104
|
+
|
105
|
+
method_type,method_name = method.split(".")
|
106
|
+
if(http_method == "GET")
|
107
|
+
url = "https://#{method_type}.#{@@domain}.gigya.com/#{method}?#{required_parameters}"
|
108
|
+
if(options)
|
109
|
+
options.each do |key,value|
|
110
|
+
url += "&#{key}=#{CGI.escape(value.to_s)}"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
else
|
114
|
+
url = "http://#{method_type}.#{@@domain}.gigya.com/#{method}"
|
115
|
+
end
|
116
|
+
url
|
117
|
+
end
|
118
|
+
|
119
|
+
#
|
120
|
+
# sends the https call to gigya and parses the result
|
121
|
+
# This is used for https get requests
|
122
|
+
#
|
123
|
+
# @param [String] method The method name to be called in the gigya api
|
124
|
+
# @param [Hash] options Hash of key value pairs passed to the gigya api
|
125
|
+
#
|
126
|
+
# @return [Hash] hash of the api results in key/value format
|
127
|
+
#
|
128
|
+
# @author Scott Sampson
|
129
|
+
def parse_results_secure(method,options)
|
130
|
+
# options = {} if options.is_a?(String) && options.blank?
|
131
|
+
begin
|
132
|
+
response = HTTParty.get(build_url(method, "GET", options),{:timeout => 10})
|
133
|
+
rescue SocketError,Timeout::Error => e
|
134
|
+
raise RGigya::ResponseError, e.message
|
135
|
+
end
|
136
|
+
return false if response.nil? || response.body == "Bad Request"
|
137
|
+
|
138
|
+
begin
|
139
|
+
doc = JSON(response.body)
|
140
|
+
rescue JSON::ParserError => e
|
141
|
+
raise RGigya::JSONParseError, e.message
|
142
|
+
end
|
143
|
+
doc
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
#
|
148
|
+
# Orders the params hash for the signature
|
149
|
+
# Changes boolean values to their string equivalent
|
150
|
+
#
|
151
|
+
# @param [Hash] h Hash of key value pairs passed to the gigya api
|
152
|
+
#
|
153
|
+
# @return [Hash] hash of the params being passed to the gigya api with their keys in alpha order
|
154
|
+
#
|
155
|
+
# @author Scott Sampson
|
156
|
+
def prepare_for_signature(h)
|
157
|
+
ordered_hash = {} #insert order with hash is preserved since ruby 1.9.2
|
158
|
+
h = h.inject({}){|p,(k,v)| p[k.to_sym] = v; p}
|
159
|
+
h.keys.sort.each do |key|
|
160
|
+
value = h[key]
|
161
|
+
if(!!value == value) #duck typeing.......quack
|
162
|
+
ordered_hash[key] = value.to_s
|
163
|
+
else
|
164
|
+
ordered_hash[key] = value
|
165
|
+
end
|
166
|
+
end
|
167
|
+
return ordered_hash
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
#
|
172
|
+
# Adds Timestamp, nonce and signatures to the params hash
|
173
|
+
#
|
174
|
+
# @param [String] request_uri the url we are using for the api call
|
175
|
+
# @param [Hash] params Hash of key value pairs passed to the gigya api
|
176
|
+
#
|
177
|
+
# @return [Hash] hash of the params being passed to the gigya api
|
178
|
+
# with timestamp, nonce and signature added
|
179
|
+
#
|
180
|
+
# @author Scott Sampson
|
181
|
+
def params_with_signature(request_uri,params)
|
182
|
+
timestamp = Time.now.utc.strftime("%s")
|
183
|
+
nonce = SigUtils::current_time_in_milliseconds()
|
184
|
+
|
185
|
+
params = {} if params.nil?
|
186
|
+
|
187
|
+
params[:format] = "json"
|
188
|
+
params[:timestamp] = timestamp
|
189
|
+
params[:nonce] = nonce
|
190
|
+
params[:apiKey] = @@api_key
|
191
|
+
|
192
|
+
normalized_url = CGI.escape(request_uri)
|
193
|
+
|
194
|
+
query_string = CGI.escape(prepare_for_signature(params).to_query)
|
195
|
+
|
196
|
+
# signature_string = SECRET + request_uri + timestamp
|
197
|
+
@@base_signature_string = "POST&#{normalized_url}&#{query_string}"
|
198
|
+
|
199
|
+
digest = SigUtils::calculate_signature(@@base_signature_string,@@api_secret)
|
200
|
+
@@signature = digest.to_s
|
201
|
+
params[:sig] = @@signature
|
202
|
+
return params
|
203
|
+
end
|
204
|
+
|
205
|
+
#
|
206
|
+
# sends the http call with signature to gigya and parses the result
|
207
|
+
# This is for http post requests
|
208
|
+
#
|
209
|
+
# @param [String] method The method name to be called in the gigya api
|
210
|
+
# @param [Hash] options Hash of key value pairs passed to the gigya api
|
211
|
+
#
|
212
|
+
# @return [Hash] hash of the api results in key/value format
|
213
|
+
#
|
214
|
+
# @author Scott Sampson
|
215
|
+
|
216
|
+
def parse_results_with_signature(method, options)
|
217
|
+
request_uri = build_url(method, "POST", options)
|
218
|
+
begin
|
219
|
+
response = HTTParty.post(request_uri, { :body => params_with_signature(request_uri,options) })
|
220
|
+
rescue URI::InvalidURIError
|
221
|
+
# need to treat this like method missing
|
222
|
+
return false
|
223
|
+
rescue SocketError,Timeout::Error => e
|
224
|
+
raise RGigya::ResponseError, e.message
|
225
|
+
end
|
226
|
+
|
227
|
+
|
228
|
+
begin
|
229
|
+
doc = JSON(response.body)
|
230
|
+
rescue JSON::ParserError => e
|
231
|
+
raise RGigya::JSONParseError, e.message
|
232
|
+
end
|
233
|
+
doc
|
234
|
+
end
|
235
|
+
|
236
|
+
|
237
|
+
#
|
238
|
+
# sends the api call to gigya and parses the result with appropriate method
|
239
|
+
#
|
240
|
+
# @param [String] method The method name to be called in the gigya api
|
241
|
+
# @param [Hash] options Hash of key value pairs passed to the gigya api
|
242
|
+
#
|
243
|
+
# @return [Hash] hash of the api results in key/value format
|
244
|
+
#
|
245
|
+
# @author Scott Sampson
|
246
|
+
def parse_results(method, options = {})
|
247
|
+
verify_config_data
|
248
|
+
return @@use_ssl ? parse_results_secure(method,options) : parse_results_with_signature(method,options)
|
249
|
+
end
|
250
|
+
|
251
|
+
#
|
252
|
+
# Error handling of the results
|
253
|
+
#
|
254
|
+
# @param [String] The method name to be called in the gigya api
|
255
|
+
# @param [Hash] results Hash of key value pairs returned by the results
|
256
|
+
#
|
257
|
+
# @return [String] hash of a successful api call
|
258
|
+
#
|
259
|
+
# TODO: Shouldn't fail so hard. If there is a temporary connectivity problem we should fail more gracefully.
|
260
|
+
# You can find a list of response codes at http://developers.gigya.com/037_API_reference/zz_Response_Codes_and_Errors
|
261
|
+
#
|
262
|
+
# @author Scott Sampson
|
263
|
+
def check_for_errors(results)
|
264
|
+
case results['errorCode'].to_s
|
265
|
+
when '0'
|
266
|
+
return results
|
267
|
+
when '400124'
|
268
|
+
#Limit Reached error - don't fail so bad
|
269
|
+
when '400002'
|
270
|
+
raise RGigya::BadParamsOrMethodName, results['errorDetails']
|
271
|
+
when '403003'
|
272
|
+
log("RGigya returned Error code #{results['errorCode']}.\n\nError Message: #{results['errorMessage']}\n\nError Details: #{results['errorDetails']}\n\n")
|
273
|
+
log("Rgigya base_signature_string = #{@@base_signature_string}\n\n")
|
274
|
+
log("Gigya base_signature_string = #{results['baseString']}\n\n\n")
|
275
|
+
log("Rgigya signature = #{@@signature}\n\n")
|
276
|
+
log("Gigya signature = #{results['expectedSignature']}\n\n")
|
277
|
+
raise RGigya::ErrorCodeReturned, "returned Error code #{results['errorCode']}: #{results['errorMessage']}"
|
278
|
+
else
|
279
|
+
log("RGigya returned Error code #{results['errorCode']}.\n\nError Message: #{results['errorMessage']}\n\nError Details: #{results['errorDetails']}")
|
280
|
+
raise RGigya::ErrorCodeReturned, "returned Error code #{results['errorCode']}: #{results['errorMessage']}"
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
##
|
285
|
+
# Override method_missing so we don't have to write all the dang methods
|
286
|
+
#
|
287
|
+
# @param [Symbol] sym The method symbol
|
288
|
+
# @param [*Array] args The splatted array of method arguments passed in
|
289
|
+
#
|
290
|
+
# @author Scott Sampson
|
291
|
+
def method_missing(sym, *args)
|
292
|
+
|
293
|
+
method = sym.to_s.gsub("_",".")
|
294
|
+
method_type,method_name = method.split(".")
|
295
|
+
|
296
|
+
if(@@valid_methods.include?(method_type.to_sym))
|
297
|
+
results = parse_results(method, args.first)
|
298
|
+
else
|
299
|
+
results = false
|
300
|
+
end
|
301
|
+
|
302
|
+
if results
|
303
|
+
return check_for_errors(results)
|
304
|
+
else
|
305
|
+
super
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
|
310
|
+
##
|
311
|
+
# Override respond_to? We can't really give an accurate return here
|
312
|
+
# I am only allowing those methods that start with the methods listed in the @@valid_methods array
|
313
|
+
#
|
314
|
+
# @param [Symbol] sym The method symbol
|
315
|
+
# @param [Boolean] include_private Whether you want to include private or not.
|
316
|
+
#
|
317
|
+
# @author Scott Sampson
|
318
|
+
def respond_to?(sym, include_private = false)
|
319
|
+
method = sym.to_s.gsub("_",".")
|
320
|
+
method_type,method_name = method.split(".")
|
321
|
+
return @@valid_methods.include?(method_type.to_sym)
|
322
|
+
end
|
323
|
+
|
324
|
+
|
325
|
+
|
326
|
+
#
|
327
|
+
# Custom log method, if we are in rails we should log any errors for debugging purposes
|
328
|
+
#
|
329
|
+
# @param [String] log_str string to log
|
330
|
+
#
|
331
|
+
# @author Scott Sampson
|
332
|
+
def log(log_str)
|
333
|
+
if Object.const_defined?('Rails')
|
334
|
+
Rails.logger.info(log_str)
|
335
|
+
else
|
336
|
+
puts log_str
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
data/lib/rgigya/hash.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#
|
2
|
+
# Mixin for ruby's Hash class
|
3
|
+
#
|
4
|
+
#
|
5
|
+
# @author Scott Sampson
|
6
|
+
# @author Michael Orr
|
7
|
+
|
8
|
+
class Hash
|
9
|
+
|
10
|
+
|
11
|
+
# returns a query string
|
12
|
+
#
|
13
|
+
# @return [String] concated string of key value pairs in the hash
|
14
|
+
#
|
15
|
+
# @author Scott Sampson
|
16
|
+
def to_query
|
17
|
+
self.map{|k,v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v)}"}.join("&")
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
#
|
2
|
+
# Utility class to help with signatures when sending api calls to gigya
|
3
|
+
#
|
4
|
+
#
|
5
|
+
# @author Scott Sampson
|
6
|
+
# @author Michael Orr
|
7
|
+
|
8
|
+
|
9
|
+
#if you think about it as a namespace the include RGigya below doesn't seem weird at all
|
10
|
+
module RGigya
|
11
|
+
|
12
|
+
class SigUtils
|
13
|
+
include RGigya
|
14
|
+
|
15
|
+
class << self
|
16
|
+
|
17
|
+
# validates the signature from the api calls having to do with authentication
|
18
|
+
# http://developers.gigya.com/010_Developer_Guide/87_Security#Validate_the_UID_Signature_in_the_Social_Login_Process
|
19
|
+
#
|
20
|
+
# @param [String] uid The id for the user who's friends you are getting
|
21
|
+
# @param [String] timestamp The signatureTimestamp passed along with api call
|
22
|
+
# @param [String] signature the UIDSignature we are verifying against
|
23
|
+
#
|
24
|
+
# @return [Boolean] true or false on whether the signature is valid
|
25
|
+
#
|
26
|
+
# @author Scott Sampson
|
27
|
+
def validate_user_signature(uid, timestamp, signature)
|
28
|
+
base = "#{timestamp}_#{uid}"
|
29
|
+
expected_signature = calculate_signature(base, @@api_secret)
|
30
|
+
return expected_signature == signature
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
# validates the signature from the api calls having to do with friends
|
35
|
+
# http://developers.gigya.com/010_Developer_Guide/87_Security#Validate_Friendship_Signatures_when_required
|
36
|
+
#
|
37
|
+
#
|
38
|
+
# @param [String] uid The id for the user who's friends you are getting
|
39
|
+
# @param [String] timestamp The signatureTimestamp passed along with each friend to verify the signature
|
40
|
+
# @param [String] friend_uid gigya's user_id for the friend
|
41
|
+
# @param [String] signature the friendshipSignature we are verifying against
|
42
|
+
#
|
43
|
+
# @return [Boolean] true or false on whether the signature is valid
|
44
|
+
#
|
45
|
+
# @author Scott Sampson
|
46
|
+
def validate_friend_signature(uid, timestamp, friend_uid, signature)
|
47
|
+
base = "#{timestamp}_#{friend_uid}_#{uid}"
|
48
|
+
expected_signature = calculate_signature(base, @@api_secret)
|
49
|
+
return expected_signature == signature
|
50
|
+
end
|
51
|
+
|
52
|
+
# generates the value for the session expiration cookie
|
53
|
+
# http://developers.gigya.com/010_Developer_Guide/87_Security#Defining_a_Session_Expiration_Cookie
|
54
|
+
#
|
55
|
+
# You want to use this if you want to terminate a session in the future
|
56
|
+
#
|
57
|
+
# @param [String] glt_cookie The login token received from Gigya after successful Login.
|
58
|
+
# Gigya stores the token in a cookie named: "glt_" + <Your API Key>
|
59
|
+
# @param [Integer] timeout_in_seconds The expiration time in seconds since Jan. 1st 1970 and in GMT/UTC timezone.
|
60
|
+
#
|
61
|
+
# @return [String] value you want to set in the cookie
|
62
|
+
#
|
63
|
+
# @author Scott Sampson
|
64
|
+
def get_dynamic_session_signature(glt_cookie, timeout_in_seconds)
|
65
|
+
expiration_time_unix_ms = (current_time_in_milliseconds().to_i/1000) + timeout_in_seconds
|
66
|
+
expiration_time_unix = expiration_time_unix_ms.floor.to_s
|
67
|
+
unsigned_expiration = "#{glt_cookie}_#{expiration_time_unix}"
|
68
|
+
signed_expiration = calculate_signature(unsigned_expiration,@@api_secret)
|
69
|
+
return "#{expiration_time_unix}_#{signed_expiration}"
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
# Returns the current utc time in milliseconds
|
74
|
+
#
|
75
|
+
# @return [String] current time in milliseconds
|
76
|
+
#
|
77
|
+
# @author Scott Sampson
|
78
|
+
def current_time_in_milliseconds()
|
79
|
+
return DateTime.now.strftime("%Q")
|
80
|
+
end
|
81
|
+
|
82
|
+
# Calulates the signature to be passed with the api calls
|
83
|
+
#
|
84
|
+
# @param [Strsing] base string that we are basing the signature off of
|
85
|
+
# @param [String] key The key we are using the encode the signature
|
86
|
+
#
|
87
|
+
# @return [String] value of the signature
|
88
|
+
#
|
89
|
+
# @author Scott Sampson
|
90
|
+
def calculate_signature(base,key)
|
91
|
+
base = base.encode('UTF-8')
|
92
|
+
raw = OpenSSL::HMAC.digest('sha1',Base64.decode64(key), base)
|
93
|
+
return Base64.encode64(raw).chomp.gsub(/\n/,'')
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/rgigya.rb
CHANGED
@@ -1,196 +1,6 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'httparty'
|
3
3
|
require 'CGI'
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
#
|
8
|
-
# You can reference api calls at http://developers.gigya.com/037_API_reference
|
9
|
-
#
|
10
|
-
# Example call
|
11
|
-
# RGigya.socialize_setStatus(:uid => @user.id,:status => 'hello')
|
12
|
-
#
|
13
|
-
# We split the method name by the underscore and then map
|
14
|
-
# the first token to the correct url using the @@urls class variable
|
15
|
-
# The example above calls the url https://socialize.gigya.com/socialize.setStatus
|
16
|
-
#
|
17
|
-
# @author Scott Sampson
|
18
|
-
|
19
|
-
|
20
|
-
#
|
21
|
-
# Constants to be used for the gigya key and secret.
|
22
|
-
# These should be commented out and set in your environments for your rails project.
|
23
|
-
# Uncomment below for testing without rails
|
24
|
-
#
|
25
|
-
# GIGYA_API_KEY = "12345"
|
26
|
-
# GIGYA_API_SECRET = "12345"
|
27
|
-
|
28
|
-
|
29
|
-
class RGigya
|
30
|
-
|
31
|
-
# Mapping to different urls based on api groupings
|
32
|
-
@@urls = {
|
33
|
-
socialize: "https://socialize-api.gigya.com",
|
34
|
-
gm: "https://gm.gigya.com",
|
35
|
-
comments: "https://comments.gigya.com",
|
36
|
-
accounts: "https://accounts.gigya.com",
|
37
|
-
reports: "https://reports.gigya.com",
|
38
|
-
chat: "https://chat.gigya.com",
|
39
|
-
ds: "https://ds.gigya.com"
|
40
|
-
}
|
41
|
-
|
42
|
-
#
|
43
|
-
# Custom Exceptions so we know it came from the library
|
44
|
-
# When in use please namespace them appropriately RGigya::ResponseError for readability
|
45
|
-
#
|
46
|
-
exceptions = %w[ UIDParamIsNil SiteUIDParamIsNil ResponseError BadParamsOrMethodName ErrorCodeReturned ]
|
47
|
-
exceptions.each { |e| const_set(e, Class.new(StandardError)) }
|
48
|
-
RGigya::JSONParseError = Class.new(JSON::ParserError)
|
49
|
-
|
50
|
-
class << self
|
51
|
-
|
52
|
-
#
|
53
|
-
# Adds the required params for all api calls
|
54
|
-
#
|
55
|
-
def required_parameters
|
56
|
-
params = "apiKey=#{CGI.escape(GIGYA_API_KEY)}"
|
57
|
-
params += "&secret=#{CGI.escape(GIGYA_API_SECRET)}"
|
58
|
-
params += "&format=json"
|
59
|
-
end
|
60
|
-
|
61
|
-
#
|
62
|
-
# builds the url to be sent to the api
|
63
|
-
#
|
64
|
-
# @param [String] method The method name to be called in the gigya api
|
65
|
-
# @param [Hash] options Hash of key value pairs passed to the gigya api
|
66
|
-
#
|
67
|
-
# @return [String] the full url to be sent to the api
|
68
|
-
#
|
69
|
-
# @author Scott Sampson
|
70
|
-
def build_url(method, options = {})
|
71
|
-
if options && options.has_key?(:uid) && options[:uid].nil?
|
72
|
-
raise RGigya::UIDParamIsNil, ""
|
73
|
-
end
|
74
|
-
|
75
|
-
if options && options.has_key?(:siteUID) && options[:siteUID].nil?
|
76
|
-
raise RGigya::SiteUIDParamIsNil, ""
|
77
|
-
end
|
78
|
-
|
79
|
-
method_type,method_name = method.split(".")
|
80
|
-
url = "#{@@urls[method_type.to_sym]}/#{method}?#{required_parameters}"
|
81
|
-
if(options)
|
82
|
-
options.each do |key,value|
|
83
|
-
url += "&#{key}=#{CGI.escape(value.to_s)}"
|
84
|
-
end
|
85
|
-
end
|
86
|
-
url
|
87
|
-
end
|
88
|
-
|
89
|
-
#
|
90
|
-
# sends the https call to gigya and parses the result
|
91
|
-
#
|
92
|
-
# @param [String] method The method name to be called in the gigya api
|
93
|
-
# @param [Hash] options Hash of key value pairs passed to the gigya api
|
94
|
-
#
|
95
|
-
# @return [Hash] hash of the api results in key/value format
|
96
|
-
#
|
97
|
-
# @author Scott Sampson
|
98
|
-
def parse_results(method, options = {})
|
99
|
-
# options = {} if options.is_a?(String) && options.blank?
|
100
|
-
begin
|
101
|
-
response = HTTParty.get(build_url(method, options),{:timeout => 10})
|
102
|
-
rescue SocketError,Timeout::Error => e
|
103
|
-
raise RGigya::ResponseError, e.message
|
104
|
-
end
|
105
|
-
return false if response.nil? || response.body == "Bad Request"
|
106
|
-
|
107
|
-
begin
|
108
|
-
doc = JSON(response.body)
|
109
|
-
rescue JSON::ParserError => e
|
110
|
-
raise RGigya::JSONParseError, e.message
|
111
|
-
end
|
112
|
-
doc
|
113
|
-
end
|
114
|
-
|
115
|
-
#
|
116
|
-
# Error handling of the results
|
117
|
-
#
|
118
|
-
# @param [String] The method name to be called in the gigya api
|
119
|
-
# @param [Hash] results Hash of key value pairs returned by the results
|
120
|
-
#
|
121
|
-
# @return [String] hash of a successful api call
|
122
|
-
#
|
123
|
-
# TODO: Shouldn't fail so hard. If there is a temporary connectivity problem we should fail more gracefully.
|
124
|
-
# You can find a list of response codes at http://developers.gigya.com/037_API_reference/zz_Response_Codes_and_Errors
|
125
|
-
#
|
126
|
-
# @author Scott Sampson
|
127
|
-
def check_for_errors(results)
|
128
|
-
case results['errorCode'].to_s
|
129
|
-
when '0'
|
130
|
-
return results
|
131
|
-
when '400124'
|
132
|
-
#Limit Reached error - don't fail so bad
|
133
|
-
when '400002'
|
134
|
-
raise RGigya::BadParamsOrMethodName, results['errorDetails']
|
135
|
-
else
|
136
|
-
log("RGigya returned Error code #{results['errorCode']}.\n\nError Message: #{results['errorMessage']}\n\nError Details: #{results['errorDetails']}")
|
137
|
-
raise RGigya::ErrorCodeReturned, "returned Error code #{results['errorCode']}: #{results['errorMessage']}"
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
##
|
142
|
-
# Override method_missing so we don't have to write all the dang methods
|
143
|
-
#
|
144
|
-
# @param [Symbol] sym The method symbol
|
145
|
-
# @param [*Array] args The splatted array of method arguments passed in
|
146
|
-
#
|
147
|
-
# @author Scott Sampson
|
148
|
-
def method_missing(sym, *args)
|
149
|
-
|
150
|
-
method = sym.to_s.gsub("_",".")
|
151
|
-
method_type,method_name = method.split(".")
|
152
|
-
if(@@urls.has_key?(method_type.to_sym))
|
153
|
-
results = parse_results(method, args.first)
|
154
|
-
else
|
155
|
-
results = false
|
156
|
-
end
|
157
|
-
|
158
|
-
if results
|
159
|
-
return check_for_errors(results)
|
160
|
-
else
|
161
|
-
super
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
|
166
|
-
##
|
167
|
-
# Override respond_to? We can't really give an accurate return here
|
168
|
-
# I am only allowing those methods that start with those methods in the @urls hash
|
169
|
-
#
|
170
|
-
# @param [Symbol] sym The method symbol
|
171
|
-
# @param [Boolean] include_private Whether you want to include private or not.
|
172
|
-
#
|
173
|
-
# @author Scott Sampson
|
174
|
-
def respond_to?(sym, include_private = false)
|
175
|
-
method = sym.to_s.gsub("_",".")
|
176
|
-
method_type,method_name = method.split(".")
|
177
|
-
return @@urls.has_key?(method_type.to_sym)
|
178
|
-
end
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
##
|
183
|
-
# Custom log method, if we are in rails we should log any errors for debugging purposes
|
184
|
-
#
|
185
|
-
# @param [String] log_str string to log
|
186
|
-
#
|
187
|
-
# @author Scott Sampson
|
188
|
-
def log(log_str)
|
189
|
-
if Object.const_defined?('Rails')
|
190
|
-
Rails.logger.info(log_str)
|
191
|
-
else
|
192
|
-
puts log_str
|
193
|
-
end
|
194
|
-
end
|
195
|
-
end
|
196
|
-
end
|
4
|
+
require File.dirname(__FILE__)+"/rgigya/base.rb"
|
5
|
+
require File.dirname(__FILE__)+"/rgigya/sig_utils.rb"
|
6
|
+
require File.dirname(__FILE__)+"/rgigya/hash.rb"
|