omnicontacts 0.1.7 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -2,3 +2,4 @@ coverage
2
2
  *.iml
3
3
  .idea
4
4
  .DS_Store
5
+ nbproject
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- omnicontacts (0.1.7)
4
+ omnicontacts (0.2.0)
5
5
  json
6
6
  rack
7
7
 
data/README.md CHANGED
@@ -36,8 +36,16 @@ On the other hand it makes things much easier to leave the default value for `:r
36
36
 
37
37
  ## Integrating with your Application
38
38
 
39
- To use OmniContacts you only need to redirect users to `/contacts/:importer`, where `:importer` can be google, yahoo or hotmail. Once the user has authorized your application, he will be redirected back to your website, to the path specified in `:redirect_path` (or `:callback_path` for yahoo). The user is redirected to `/contacts/:importer/callback` by default, which therefore makes things much simpler to not specify any value for `:redirect_path` or `:callback_path`.
40
- The list of contacts can be accessed via the `omnicontacts.contacts` key in the environment hash. The list of contacts is a simple array of hashes. Each hash has two keys: `:email` and `:name`, containing the email and the name of the contact respectively.
39
+ To use the Gem you first need to redirect your users to `/contacts/:importer`, where `:importer` can be google, yahoo or hotmail.
40
+ No changes to `config/routes.rb` are needed for this step since OmniContacts will be listening on that path and redirect the user to the email provider's website in order to authorize your app to access his contact list.
41
+ Once that is done the user will be redirected back to your application, to the path specified in `:redirect_path` (or `:callback_path` for yahoo).
42
+ If nothing is specified the default value is `/contacts/:importer/callback` (e.g. `/contacts/yahoo/callback`). This makes things simpler and you can just add the following line to `config/routes.rb`:
43
+
44
+ ```ruby
45
+ match "/contacts/:importer/callback" => "your_controller#callback"
46
+ ```
47
+
48
+ The list of contacts can be accessed via the `omnicontacts.contacts` key in the environment hash. It is a simple array of hashes. Each hash has two keys: `:email` and `:name`, containing the email and the name of the contact respectively.
41
49
 
42
50
  ```ruby
43
51
  def contacts_callback
data/Rakefile CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'bundler'
2
- Bundler::GemHelper.install_tasks
3
2
  require 'rspec/core/rake_task'
3
+
4
+ Bundler::GemHelper.install_tasks
4
5
  RSpec::Core::RakeTask.new(:spec)
5
6
  task :default => :spec
6
7
  task :test => :spec
data/lib/omnicontacts.rb CHANGED
@@ -1,11 +1,16 @@
1
1
  module OmniContacts
2
-
3
- VERSION = "0.1.7"
2
+
3
+ VERSION = "0.2.0"
4
4
 
5
5
  autoload :Builder, "omnicontacts/builder"
6
6
  autoload :Importer, "omnicontacts/importer"
7
+ autoload :IntegrationTest, "omnicontacts/integration_test"
7
8
 
8
9
  class AuthorizationError < RuntimeError
9
10
  end
10
-
11
- end
11
+
12
+ def self.integration_test
13
+ IntegrationTest.instance
14
+ end
15
+
16
+ end
@@ -27,13 +27,13 @@ module OmniContacts
27
27
 
28
28
  def authorize_url_params
29
29
  to_query_string({
30
- :client_id => client_id,
31
- :scope => encode(scope),
32
- :response_type => "code",
33
- :access_type => "offline",
34
- :approval_prompt => "force",
35
- :redirect_uri => encode(redirect_uri)
36
- })
30
+ :client_id => client_id,
31
+ :scope => encode(scope),
32
+ :response_type => "code",
33
+ :access_type => "offline",
34
+ :approval_prompt => "force",
35
+ :redirect_uri => encode(redirect_uri)
36
+ })
37
37
  end
38
38
 
39
39
  public
@@ -36,7 +36,7 @@ module OmniContacts
36
36
  def host_url_from_rack_env env
37
37
  port = ((env["SERVER_PORT"] == 80) && "") || ":#{env['SERVER_PORT']}"
38
38
  host = (env["HTTP_HOST"]) || (env["SERVER_NAME"] + port)
39
- scheme(env) + "://" + host
39
+ "#{scheme(env)}://#{host}"
40
40
  end
41
41
 
42
42
  def scheme env
@@ -45,7 +45,7 @@ module OmniContacts
45
45
  elsif env['HTTP_X_FORWARDED_SSL'] == 'on'
46
46
  'https'
47
47
  elsif env['HTTP_X_FORWARDED_PROTO']
48
- env['HTTP_X_FORWARDED_PROTO'].split(',')[0]
48
+ env['HTTP_X_FORWARDED_PROTO'].split(',').first
49
49
  else
50
50
  env["rack.url_scheme"]
51
51
  end
@@ -0,0 +1,36 @@
1
+ require 'singleton'
2
+
3
+ class IntegrationTest
4
+ include Singleton
5
+
6
+ attr_accessor :enabled
7
+
8
+ def initialize
9
+ enabled = false
10
+ clear_mocks
11
+ end
12
+
13
+ def clear_mocks
14
+ @mock = {}
15
+ end
16
+
17
+ def mock provider, mock
18
+ @mock[provider.to_sym] = mock
19
+ end
20
+
21
+ def mock_authorization_from_user provider
22
+ [302, {"location" => provider.redirect_path}, []]
23
+ end
24
+
25
+ def mock_fetch_contacts provider
26
+ result = @mock[provider.class_name.to_sym] || []
27
+ if result.is_a? Array
28
+ result
29
+ elsif result.is_a? Hash
30
+ [result]
31
+ else
32
+ raise result.to_s
33
+ end
34
+ end
35
+
36
+ end
@@ -17,16 +17,12 @@ module OmniContacts
17
17
  @ssl_ca_file = options[:ssl_ca_file]
18
18
  end
19
19
 
20
- private
21
-
22
20
  def class_name
23
21
  self.class.name.split('::').last.downcase
24
22
  end
25
23
 
26
- public
27
-
28
24
  # Rack callback. It handles three cases:
29
- # * user visit middleware entru point.
25
+ # * user visit middleware entry point.
30
26
  # In this case request_authorization_from_user is called
31
27
  # * user is redirected back to the application
32
28
  # from the authorization site. In this case the list
@@ -47,16 +43,28 @@ module OmniContacts
47
43
  end
48
44
 
49
45
  private
46
+
47
+ def test_mode?
48
+ IntegrationTest.instance.enabled
49
+ end
50
50
 
51
51
  def handle_initial_request
52
52
  execute_and_rescue_exceptions do
53
- request_authorization_from_user
53
+ if test_mode?
54
+ IntegrationTest.instance.mock_authorization_from_user(self)
55
+ else
56
+ request_authorization_from_user
57
+ end
54
58
  end
55
59
  end
56
60
 
57
61
  def handle_callback
58
62
  execute_and_rescue_exceptions do
59
- @env["omnicontacts.contacts"] = fetch_contacts
63
+ @env["omnicontacts.contacts"] = if test_mode?
64
+ IntegrationTest.instance.mock_fetch_contacts(self)
65
+ else
66
+ fetch_contacts
67
+ end
60
68
  @app.call(@env)
61
69
  end
62
70
  end
@@ -18,7 +18,7 @@ module OmniContacts
18
18
  super app, options
19
19
  @consumer_key = consumer_key
20
20
  @consumer_secret = consumer_secret
21
- @callback_path = options[:callback_path] ||= "/contacts/#{class_name}/callback"
21
+ @callback_path = options[:callback_path] || "/contacts/#{class_name}/callback"
22
22
  @token_prop_name = "#{base_prop_name}.oauth_token"
23
23
  end
24
24
 
@@ -19,7 +19,7 @@ module OmniContacts
19
19
  super app, options
20
20
  @client_id = client_id
21
21
  @client_secret = client_secret
22
- @redirect_path = options[:redirect_path] ||= "/contacts/#{class_name}/callback"
22
+ @redirect_path = options[:redirect_path] || "/contacts/#{class_name}/callback"
23
23
  @ssl_ca_file = options[:ssl_ca_file]
24
24
  end
25
25
 
@@ -0,0 +1,51 @@
1
+ require "spec_helper"
2
+ require "omnicontacts/integration_test"
3
+
4
+ describe IntegrationTest do
5
+
6
+ context "mock_initial_request" do
7
+ it "should redirect to the provider's redirect_path" do
8
+ provider = mock
9
+ redirect_path = "/redirect_path"
10
+ provider.stub(:redirect_path => redirect_path)
11
+ IntegrationTest.instance.mock_authorization_from_user(provider)[1]["location"].should eq(redirect_path)
12
+ end
13
+ end
14
+
15
+ context "mock_callback" do
16
+
17
+ before(:each) {
18
+ @env = {}
19
+ @provider = self.mock
20
+ @provider.stub(:class_name => "test")
21
+ IntegrationTest.instance.clear_mocks
22
+ }
23
+
24
+ it "should return an empty contacts list" do
25
+ IntegrationTest.instance.mock_fetch_contacts(@provider).should be_empty
26
+ end
27
+
28
+ it "should return a configured list of contacts " do
29
+ contacts = [:name => 'John Doe', :email => 'john@doe.com']
30
+ IntegrationTest.instance.mock('test', contacts)
31
+ result = IntegrationTest.instance.mock_fetch_contacts(@provider)
32
+ result.size.should be(1)
33
+ result.first[:email].should eq(contacts.first[:email])
34
+ result.first[:name].should eq(contacts.first[:name])
35
+ end
36
+
37
+ it "should return a single element list of contacts " do
38
+ contact = {:name => 'John Doe', :email => 'john@doe.com'}
39
+ IntegrationTest.instance.mock('test', contact)
40
+ result = IntegrationTest.instance.mock_fetch_contacts(@provider)
41
+ result.size.should be(1)
42
+ result.first[:email].should eq(contact[:email])
43
+ result.first[:name].should eq(contact[:name])
44
+ end
45
+
46
+ it "should throw an exception" do
47
+ IntegrationTest.instance.mock('test', :some_error)
48
+ expect {IntegrationTest.instance.mock_fetch_contacts(@provider)}.should raise_error
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,46 @@
1
+ require "spec_helper"
2
+ require "omnicontacts/middleware/base_oauth"
3
+
4
+ describe OmniContacts::Middleware::BaseOAuth do
5
+
6
+ before(:all) do
7
+ class TestProvider < OmniContacts::Middleware::BaseOAuth
8
+ def initialize app, consumer_key, consumer_secret, options = {}
9
+ super app, options
10
+ end
11
+
12
+ def redirect_path
13
+ "/contacts/testprovider/callback"
14
+ end
15
+ end
16
+ OmniContacts.integration_test.enabled = true
17
+ end
18
+
19
+ let(:app) {
20
+ Rack::Builder.new do |b|
21
+ b.use TestProvider, "consumer_id", "consumer_secret"
22
+ b.run lambda { |env| [200, {"Content-Type" => "text/html"}, ["Hello World"]] }
23
+ end.to_app
24
+ }
25
+
26
+ it "should return a preconfigured list of contacts" do
27
+ OmniContacts.integration_test.mock(:testprovider, :email => "user@example.com")
28
+ get "/contacts/testprovider"
29
+ get "/contacts/testprovider/callback"
30
+ last_request.env["omnicontacts.contacts"].first[:email].should eq("user@example.com")
31
+ end
32
+
33
+ it "should redurect to failure url" do
34
+ OmniContacts.integration_test.mock(:testprovider, "some_error" )
35
+ get "/contacts/testprovider"
36
+ get "/contacts/testprovider/callback"
37
+ last_response.should be_redirect
38
+ last_response.headers["location"].should eq("/contacts/failure?error_message=internal_error")
39
+ end
40
+
41
+ after(:all) do
42
+ OmniContacts.integration_test.enabled = false
43
+ OmniContacts.integration_test.clear_mocks
44
+ end
45
+
46
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omnicontacts
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-07 00:00:00.000000000 Z
12
+ date: 2012-06-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -129,6 +129,7 @@ files:
129
129
  - lib/omnicontacts/importer/gmail.rb
130
130
  - lib/omnicontacts/importer/hotmail.rb
131
131
  - lib/omnicontacts/importer/yahoo.rb
132
+ - lib/omnicontacts/integration_test.rb
132
133
  - lib/omnicontacts/middleware/base_oauth.rb
133
134
  - lib/omnicontacts/middleware/oauth1.rb
134
135
  - lib/omnicontacts/middleware/oauth2.rb
@@ -139,6 +140,8 @@ files:
139
140
  - spec/omnicontacts/importer/gmail_spec.rb
140
141
  - spec/omnicontacts/importer/hotmail_spec.rb
141
142
  - spec/omnicontacts/importer/yahoo_spec.rb
143
+ - spec/omnicontacts/integration_test_spec.rb
144
+ - spec/omnicontacts/middleware/base_oauth_spec.rb
142
145
  - spec/omnicontacts/middleware/oauth1_spec.rb
143
146
  - spec/omnicontacts/middleware/oauth2_spec.rb
144
147
  - spec/spec_helper.rb