databasedotcom-oauth2 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ notes.txt
2
+ databasedotcom-oauth2-0.0.1.gem
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in omniauth-salesforce.gemspec
4
+ gemspec
5
+
6
+ group :development, :test do
7
+ gem 'guard'
8
+ gem 'guard-rspec'
9
+ gem 'guard-bundler'
10
+ gem 'rb-fsevent'
11
+ gem 'growl'
12
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,81 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ databasedotcom-oauth2 (0.0.5)
5
+ addressable
6
+ databasedotcom
7
+ oauth2
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ addressable (2.2.8)
13
+ crack (0.3.1)
14
+ databasedotcom (1.3.0)
15
+ json
16
+ multipart-post (~> 1.1)
17
+ diff-lcs (1.1.3)
18
+ faraday (0.8.1)
19
+ multipart-post (~> 1.1)
20
+ ffi (1.0.11)
21
+ growl (1.0.3)
22
+ guard (1.1.1)
23
+ listen (>= 0.4.2)
24
+ thor (>= 0.14.6)
25
+ guard-bundler (0.1.3)
26
+ bundler (>= 1.0.0)
27
+ guard (>= 0.2.2)
28
+ guard-rspec (1.0.0)
29
+ guard (>= 1.1)
30
+ httpauth (0.1)
31
+ json (1.7.3)
32
+ listen (0.4.4)
33
+ rb-fchange (~> 0.0.5)
34
+ rb-fsevent (~> 0.9.1)
35
+ rb-inotify (~> 0.8.8)
36
+ multi_json (1.3.6)
37
+ multipart-post (1.1.5)
38
+ oauth2 (0.7.1)
39
+ faraday (~> 0.8)
40
+ httpauth (~> 0.1)
41
+ multi_json (~> 1.0)
42
+ rack (~> 1.4)
43
+ rack (1.4.1)
44
+ rack-test (0.6.1)
45
+ rack (>= 1.0)
46
+ rb-fchange (0.0.5)
47
+ ffi
48
+ rb-fsevent (0.9.1)
49
+ rb-inotify (0.8.8)
50
+ ffi (>= 0.5.0)
51
+ rspec (2.10.0)
52
+ rspec-core (~> 2.10.0)
53
+ rspec-expectations (~> 2.10.0)
54
+ rspec-mocks (~> 2.10.0)
55
+ rspec-core (2.10.1)
56
+ rspec-expectations (2.10.0)
57
+ diff-lcs (~> 1.1.3)
58
+ rspec-mocks (2.10.1)
59
+ simplecov (0.6.4)
60
+ multi_json (~> 1.0)
61
+ simplecov-html (~> 0.5.3)
62
+ simplecov-html (0.5.3)
63
+ thor (0.15.2)
64
+ webmock (1.8.7)
65
+ addressable (>= 2.2.7)
66
+ crack (>= 0.1.7)
67
+
68
+ PLATFORMS
69
+ ruby
70
+
71
+ DEPENDENCIES
72
+ databasedotcom-oauth2!
73
+ growl
74
+ guard
75
+ guard-bundler
76
+ guard-rspec
77
+ rack-test
78
+ rb-fsevent
79
+ rspec (~> 2.7)
80
+ simplecov
81
+ webmock
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # databasedotcom-oauth2
2
+
3
+ Rack Middleware for OAuth2 authentication against, and interaction with salesforce.com via the databasedotcom gem.
4
+
5
+ ### Who's it for?
6
+
7
+ RubyDevelopers of
8
+ Whereas OmniAuth only provides authentication, this Rack Middleware assumes you lso instantiates a Databasedotcom::Client while providing an
9
+
10
+ authentication and you need to query or manipulate salesforce.com data in addition to authentication.
11
+
12
+ ### Benefits:
13
+
14
+ * Hides OAuth2 hand-shake complexity against multiple salesforce.com endpoints (prod vs sandbox) including support for My Domain.
15
+ * Configurable/override-able options for scope, display, immediate
16
+ * OAuth2 Token encrypted and stored in session, supports any Rack:Session type - Cookie, Pool, etc.
17
+ * Materializes Databasedotcom::Client from token upon each request
18
+ * Databasedotcom::OAuth2::Helpers mixin provides convenience methods client, me, etc.
19
+
20
+ ## Demos
21
+
22
+ <a href="https://db-oauth2-sinatra-basic.herokuapp.com" target="_blank">Sinatra Basic</a><a href="https://github.com/richardvanhook/databasedotcom-oauth2-sinatra-basic" target="_blank">(source)</a>
23
+
24
+ <a href="https://db-oauth2-sinatra-jqm.herokuapp.com" target="_blank">Sinatra showing authentication options along with JQuery Mobile</a><a href="https://github.com/richardvanhook/databasedotcom-oauth2-sinatra-jqm" target="_blank">(source)</a>
25
+
26
+ ## Usage
27
+
28
+ ### Required
29
+
30
+ `:token_encryption_key` & `:endpoints` are required. databasedotcom-oauth2 encrypts oauth2 token using `:token_encryption_key` and stores it in rack.session for further use. `:endpoints` defines the server endpoints to be available; multiple can be specified but at least one is required.
31
+
32
+ ```ruby
33
+ use Databasedotcom::OAuth2::WebServerFlow,
34
+ :token_encryption_key => TOKEN_ENCRYPTION_KEY,
35
+ :endpoints => {"login.salesforce.com" => {:keys => CLIENT_ID, :secret => CLIENT_SECRET}}
36
+ ```
37
+
38
+ ### Multiple Endpoints
39
+
40
+ ```ruby
41
+ use Databasedotcom::OAuth2::WebServerFlow,
42
+ :endpoints => {"login.salesforce.com" => {:keys => CLIENT_ID1, :secret => CLIENT_SECRET1},
43
+ "test.salesforce.com" => {:keys => CLIENT_ID2, :secret => CLIENT_SECRET2}}
44
+ ```
45
+ ### Authentication Options
46
+ ```ruby
47
+ use Databasedotcom::OAuth2::WebServerFlow,
48
+ :scope => "full", #default is "id api refresh_token"
49
+ :display => "touch", #default is "page"
50
+ :immediate => true #default is false
51
+ :scope_override => true, #default is false
52
+ :display_override => true, #default is false
53
+ :immediate_override => true, #default is false
54
+ ```
55
+
56
+ ## Parameters
57
+
58
+ ### `:endpoints`
59
+
60
+
61
+
62
+ ### `:token_encryption_key`
63
+
64
+ It's uber important that `:token_encryption_key` is sufficiently strong. To generate a sufficiently strong key, run following:
65
+
66
+ $ ruby -ropenssl -rbase64 -e "puts Base64.strict_encode64(OpenSSL::Random.random_bytes(16).to_str)"
67
+
68
+ Then, in your code, decrypt prior using:
69
+
70
+ ```ruby
71
+ Base64.strict_decode64(TOKEN_ENCRYPTION_KEY)
72
+ ```
73
+
74
+ ## Resources
75
+
76
+ * [Article: Digging Deeper into OAuth 2.0 on Force.com](http://wiki.developerforce.com/index.php/Digging_Deeper_into_OAuth_2.0_on_Force.com)
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rspec/core/rake_task'
4
+
5
+ desc 'Default: run specs.'
6
+ task :default => :spec
7
+
8
+ desc "Run specs"
9
+ RSpec::Core::RakeTask.new
10
+
11
+ desc 'Run specs'
12
+ task :default => :spec
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/databasedotcom-oauth2/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Richard Vanhook"]
6
+ gem.email = ["rvanhook@salesforce.com"]
7
+ gem.description = %q{OAuth2 Rack Middleware for database.com/salesforce.com.}
8
+ gem.summary = %q{OAuth2 Rack Middleware for database.com/salesforce.com.}
9
+ gem.homepage = "https://github.com/richardvanhook/databasedotcom-oauth2"
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = "databasedotcom-oauth2"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Databasedotcom::OAuth2::VERSION
17
+
18
+ gem.add_dependency 'addressable'
19
+ gem.add_dependency 'hashie'
20
+ gem.add_dependency 'gibberish'
21
+ gem.add_dependency 'databasedotcom'
22
+ gem.add_dependency 'oauth2'
23
+
24
+ gem.add_development_dependency 'rspec', '~> 2.7'
25
+ gem.add_development_dependency 'rack-test'
26
+ gem.add_development_dependency 'simplecov'
27
+ gem.add_development_dependency 'webmock'
28
+ end
@@ -0,0 +1,5 @@
1
+ module Databasedotcom
2
+ module OAuth2
3
+ VERSION = "0.1.7"
4
+ end
5
+ end
@@ -0,0 +1,366 @@
1
+ require "cgi"
2
+ require "base64"
3
+ require "openssl"
4
+ require "addressable/uri"
5
+ require "hashie"
6
+ require "gibberish"
7
+ require "databasedotcom"
8
+ require "oauth2"
9
+
10
+ module OAuth2
11
+ class AccessToken
12
+ attr_accessor :client
13
+ end
14
+ end
15
+
16
+ module Databasedotcom
17
+
18
+ class Client
19
+ def self.from_token(token, api_version)
20
+ client = nil
21
+ unless token.nil?
22
+ client = self.new({
23
+ :client_id => token.client.id,
24
+ :client_secret => token.client.secret,
25
+ :host => token.client.site
26
+ })
27
+ m = token["id"].match(/\/id\/([^\/]+)\/([^\/]+)$/)
28
+ client.org_id = m[1] rescue nil
29
+ client.user_id = m[2] rescue nil
30
+ client.version = api_version
31
+ client.instance_url = token.client.site
32
+ client.oauth_token = token.token
33
+ client.refresh_token = token.refresh_token
34
+ end
35
+ client
36
+ end
37
+
38
+ def org_id=(val)
39
+ @org_id = val
40
+ end
41
+
42
+ def user_id=(val)
43
+ @user_id = val
44
+ end
45
+
46
+ end
47
+
48
+ module OAuth2
49
+ TOKEN_KEY = "databasedotcom.token"
50
+ CLIENT_KEY = "databasedotcom.client"
51
+
52
+ module Helpers
53
+ def client
54
+ env['databasedotcom.client']
55
+ end
56
+
57
+ def token
58
+ env['databasedotcom.token']
59
+ end
60
+
61
+ def unauthenticated?
62
+ client.nil?
63
+ end
64
+
65
+ def authenticated?
66
+ !unauthenticated?
67
+ end
68
+
69
+ def me
70
+ @me ||= ::Hashie::Mash.new(Databasedotcom::Chatter::User.find(client, "me").raw_hash)
71
+ #@me.organization_id
72
+ end
73
+ end
74
+
75
+ class WebServerFlow
76
+
77
+ def initialize(app, options = nil)
78
+ @app = app
79
+ unless options.nil?
80
+ @endpoints = self.class.sanitize_endpoints(options[:endpoints])
81
+ @token_encryption_key = options[:token_encryption_key]
82
+ @path_prefix = options[:path_prefix]
83
+ @on_failure = options[:on_failure]
84
+ @scope = options[:scope]
85
+ @display = options[:display]
86
+ @immediate = options[:immediate]
87
+ @scope_override = options[:scope_override] || false
88
+ @display_override = options[:display_override] || false
89
+ @immediate_override = options[:immediate_override] || false
90
+ @api_version = options[:api_version] || "24.0"
91
+ end
92
+
93
+ fail "\n\ndatabasedotcom-oauth2 initialization error! :endpoints parameter " \
94
+ + "is invalid. Do something like this:\n\nuse Databasedotcom::OAuth2::Web" \
95
+ + "ServerFlow, :endpoints => {\"login.salesforce.com\" => { :key => CLIENT" \
96
+ + "_ID_FROM_DATABASEDOTCOM, :secret => CLIENT_SECRET_FROM_DATABASEDOTCOM }" \
97
+ + "}\n\n" \
98
+ if !@endpoints.is_a?(Hash) || @endpoints.empty?
99
+
100
+ fail "\n\ndatabasedotcom-oauth2 initialization error! :token_encryption_key " \
101
+ + "is invalid. Do something like this:\n\nuse Databasedotcom::OAuth2::WebS" \
102
+ + "erverFlow, :token_encryption_key => YOUR_VERY_LONG_VERY_RANDOM_SECRET_KE" \
103
+ + "Y_HERE\n\nTo generate a sufficiently long random key, use following comm" \
104
+ + "and:\n\n$ ruby -ropenssl -rbase64 -e \"puts Base64.strict_encode64(OpenS" \
105
+ + "SL::Random.random_bytes(16).to_str)\"\n\n" \
106
+ if @token_encryption_key.nil? || @token_encryption_key.size < 16
107
+
108
+ @path_prefix = "/auth/salesforce" unless @path_prefix.is_a?(String) && !@path_prefix.strip.empty?
109
+ @on_failure = nil unless @on_failure.is_a?(Proc)
110
+ end
111
+
112
+ def call(env)
113
+ dup.call!(env)
114
+ end
115
+
116
+ def call!(env)
117
+ @env = env
118
+ begin
119
+ return authorize_call if on_authorize_path?
120
+ return callback_call if on_callback_path?
121
+ materialize_token_and_client_from_session_if_present
122
+ rescue Exception => e
123
+ self.class._log_exception(e)
124
+ if @on_failure.nil?
125
+ new_path = Addressable::URI.parse(@path_prefix + "/failure")
126
+ new_path.query_values={:message => e.message, :state => request.params['state']}
127
+ return [302, {'Location' => new_path.to_s, 'Content-Type'=> 'text/html'}, []]
128
+ else
129
+ return @on_failure.call(env,e)
130
+ end
131
+ end
132
+ @app.call(env)
133
+ end
134
+
135
+ private
136
+
137
+ def on_authorize_path?
138
+ on_path?(@path_prefix)
139
+ end
140
+
141
+ def authorize_call
142
+ #determine endpoint via param; but if blank, use default
143
+ endpoint = request.params["endpoint"] #get endpoint from http param
144
+ keys = @endpoints[endpoint] #if endpoint not found, default will be used
145
+ endpoint = @endpoints.invert[keys] #re-lookup endpoint in case original param was bogus
146
+ mydomain = self.class.sanitize_mydomain(request.params["mydomain"])
147
+
148
+ #add endpoint to relay state so callback knows which keys to use
149
+ request.params["state"] ||= "/"
150
+ state = Addressable::URI.parse(request.params["state"])
151
+ state.query_values={} unless state.query_values
152
+ state.query_values= state.query_values.merge({:endpoint => endpoint})
153
+
154
+ #build params hash to be passed to ouath2 authorize redirect url
155
+ auth_params = {
156
+ :redirect_uri => "#{full_host}#{@path_prefix}/callback",
157
+ :state => state.to_s
158
+ }
159
+ auth_params[:scope] = @scope unless @scope.nil? || @scope.strip.empty?
160
+ auth_params[:display] = @display unless @display.nil?
161
+ auth_params[:immediate] = @immediate unless @immediate.nil?
162
+
163
+ #overrides
164
+ overrides = {}
165
+ if @scope_override
166
+ scope = (self.class.param_repeated(request.url, :scope) || []).join(" ")
167
+ overrides[:scope] = scope unless scope.nil? || scope.strip.empty?
168
+ end
169
+ overrides[:display] = request.params["display"] unless !@display_override || request.params["display"].nil?
170
+ overrides[:immediate] = request.params["immediate"] unless !@immediate_override || request.params["immediate"].nil?
171
+ auth_params.merge!(overrides)
172
+
173
+ #do redirect
174
+ redirect client(mydomain || endpoint, keys[:key], keys[:secret]).auth_code.authorize_url(auth_params)
175
+ end
176
+
177
+ def on_callback_path?
178
+ on_path?(@path_prefix + "/callback")
179
+ end
180
+
181
+ def callback_call
182
+ #check for error
183
+ callback_error = request.params["error"]
184
+ callback_error_details = request.params["error_description"]
185
+ fail "#{callback_error} #{callback_error_details}" unless callback_error.nil? || callback_error.strip.empty?
186
+
187
+ #grab authorization code
188
+ code = request.params["code"]
189
+ #grab and remove endpoint from relay state
190
+ #upon successful retrieval of token, state is url where user will be redirected to
191
+ request.params["state"] ||= "/"
192
+ state = Addressable::URI.parse(request.params["state"])
193
+ state.query_values= {} if state.query_values.nil?
194
+ state_params = state.query_values.dup
195
+ endpoint = state_params.delete("endpoint")
196
+ keys = @endpoints[endpoint]
197
+ state.query_values= state_params
198
+ state = state.to_s
199
+ state.sub!(/\?$/,"") unless state.nil?
200
+
201
+ #do callout to retrieve token
202
+ access_token = client(endpoint, keys[:key], keys[:secret]).auth_code.get_token(code,
203
+ :redirect_uri => "#{full_host}#{@path_prefix}/callback")
204
+ access_token.options[:mode] = :query
205
+ access_token.options[:param_name] = :oauth_token
206
+ access_token.options[:endpoint] = endpoint
207
+ access_token.client = nil
208
+
209
+ #populate session with serialized, encrypted token
210
+ #will be used later to materialize actual token and databasedotcom client handle
211
+ set_session_token(encrypt(access_token))
212
+ redirect state.to_str
213
+ end
214
+
215
+ def materialize_token_and_client_from_session_if_present
216
+ access_token = decrypt(session_token) unless session_token.nil? rescue nil
217
+ unless access_token.nil?
218
+ instance_url = access_token.params["instance_url"]
219
+ endpoint = access_token.options[:endpoint]
220
+ keys = @endpoints[endpoint]
221
+ access_token.client = client(instance_url, keys[:key], keys[:secret])
222
+ unless keys.nil?
223
+ @env[TOKEN_KEY] = access_token
224
+ @env[CLIENT_KEY] = ::Databasedotcom::Client.from_token(@env[TOKEN_KEY],@api_version)
225
+ end
226
+ end
227
+ end
228
+
229
+ def session
230
+ @env["rack.session"] ||= {} #in case session is nil
231
+ @env["rack.session"]
232
+ end
233
+
234
+ def session_token
235
+ session[TOKEN_KEY]
236
+ end
237
+
238
+ def set_session_token(value)
239
+ session[TOKEN_KEY] = value
240
+ end
241
+
242
+ def aes
243
+ Gibberish::AES.new(@token_encryption_key)
244
+ end
245
+
246
+ def encrypt(data)
247
+ aes.encrypt(Marshal.dump(data))
248
+ end
249
+
250
+ def decrypt(data)
251
+ Marshal.load(aes.decrypt(data))
252
+ end
253
+
254
+ def on_path?(path)
255
+ current_path.casecmp(path) == 0
256
+ end
257
+
258
+ def current_path
259
+ request.path_info.downcase.sub(/\/$/,'')
260
+ end
261
+
262
+ def query_string
263
+ request.query_string.empty? ? "" : "?#{request.query_string}"
264
+ end
265
+
266
+ def request
267
+ @request ||= Rack::Request.new(@env)
268
+ end
269
+
270
+ def full_host
271
+ full_host = ENV['ORIGIN']
272
+ if full_host.nil? || full_host.strip.empty?
273
+ full_host = URI.parse(request.url.gsub(/\?.*$/,''))
274
+ full_host.path = ''
275
+ full_host.query = nil
276
+ #sometimes the url is actually showing http inside rails because the other layers (like nginx) have handled the ssl termination.
277
+ full_host.scheme = 'https' if(request.env['HTTP_X_FORWARDED_PROTO'] == 'https')
278
+ full_host = full_host.to_s
279
+ end
280
+ full_host
281
+ end
282
+
283
+ def client(site, client_id, client_secret)
284
+ ::OAuth2::Client.new(
285
+ client_id,
286
+ client_secret,
287
+ :site => "https://#{self.class.parse_domain(site)}",
288
+ :authorize_url => '/services/oauth2/authorize',
289
+ :token_url => '/services/oauth2/token'
290
+ )
291
+ end
292
+
293
+ def redirect(uri)
294
+ r = Rack::Response.new
295
+ r.write("Redirecting to #{uri}...")
296
+ r.redirect(uri)
297
+ r.finish
298
+ end
299
+
300
+ class << self
301
+
302
+ def _log_exception(exception)
303
+ STDERR.puts "\n\n#{exception.class} (#{exception.message}):\n " +
304
+ exception.backtrace.join("\n ") +
305
+ "\n\n"
306
+ end
307
+
308
+ def sanitize_mydomain(mydomain)
309
+ mydomain = parse_domain(mydomain)
310
+ mydomain = nil unless mydomain.nil? || !mydomain.strip.empty?
311
+ mydomain = mydomain.split(/\.my\.salesforce\.com/).first + ".my.salesforce.com" unless mydomain.nil?
312
+ mydomain
313
+ end
314
+
315
+ def sanitize_endpoints(endpoints = nil)
316
+ endpoints = {} unless endpoints.is_a?(Hash)
317
+ endpoints = endpoints.dup
318
+ endpoints.keep_if do |key,value|
319
+ value.is_a?(Hash) &&
320
+ value.has_key?(:key) &&
321
+ value.has_key?(:secret) &&
322
+ !value[:key].nil? &&
323
+ !value[:secret].nil? &&
324
+ !value[:key].empty? &&
325
+ !value[:secret].empty?
326
+ end
327
+ #set random default if default isn't already populated
328
+ if !endpoints.empty? && endpoints.default.nil?
329
+ endpoints.default = endpoints[endpoints.keys.first]
330
+ end
331
+ endpoints
332
+ end
333
+
334
+ def parse_domain(url = nil)
335
+ unless url.nil?
336
+ url = "https://" + url if (url =~ /http[s]?:\/\//).nil?
337
+ begin
338
+ url = Addressable::URI.parse(url)
339
+ rescue Addressable::URI::InvalidURIError
340
+ url = nil
341
+ end
342
+ url = url.host unless url.nil?
343
+ url.strip! unless url.nil?
344
+ end
345
+ url = nil if url && url.strip.empty?
346
+ url
347
+ end
348
+
349
+ def param_repeated(url = nil, param_name = nil)
350
+ return_value = nil
351
+ unless url.nil? || url.strip.empty? || param_name.nil?
352
+ url = Addressable::URI.parse(url)
353
+ param_name = param_name.to_s if param_name.is_a?(Symbol)
354
+ query_values = url.query_values(:notation => :flat_array)
355
+ unless query_values.nil? || query_values.empty?
356
+ return_value = query_values.select{|param| param.is_a?(Array) && param.size >= 2 && param[0] == param_name}.collect{|param| param[1]}
357
+ end
358
+ end
359
+ return_value
360
+ end
361
+
362
+ end
363
+ end
364
+
365
+ end
366
+ end
metadata ADDED
@@ -0,0 +1,198 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: databasedotcom-oauth2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.7
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Richard Vanhook
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-26 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: addressable
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: hashie
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: gibberish
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: databasedotcom
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: oauth2
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: rspec
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: '2.7'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: '2.7'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rack-test
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: simplecov
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: webmock
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ description: OAuth2 Rack Middleware for database.com/salesforce.com.
159
+ email:
160
+ - rvanhook@salesforce.com
161
+ executables: []
162
+ extensions: []
163
+ extra_rdoc_files: []
164
+ files:
165
+ - .gitignore
166
+ - Gemfile
167
+ - Gemfile.lock
168
+ - MIT-LICENSE
169
+ - README.md
170
+ - Rakefile
171
+ - databasedotcom-oauth2.gemspec
172
+ - lib/databasedotcom-oauth2.rb
173
+ - lib/databasedotcom-oauth2/version.rb
174
+ homepage: https://github.com/richardvanhook/databasedotcom-oauth2
175
+ licenses: []
176
+ post_install_message:
177
+ rdoc_options: []
178
+ require_paths:
179
+ - lib
180
+ required_ruby_version: !ruby/object:Gem::Requirement
181
+ none: false
182
+ requirements:
183
+ - - ! '>='
184
+ - !ruby/object:Gem::Version
185
+ version: '0'
186
+ required_rubygems_version: !ruby/object:Gem::Requirement
187
+ none: false
188
+ requirements:
189
+ - - ! '>='
190
+ - !ruby/object:Gem::Version
191
+ version: '0'
192
+ requirements: []
193
+ rubyforge_project:
194
+ rubygems_version: 1.8.24
195
+ signing_key:
196
+ specification_version: 3
197
+ summary: OAuth2 Rack Middleware for database.com/salesforce.com.
198
+ test_files: []