dropbox 1.1.1 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -23,3 +23,4 @@ pkg
23
23
  .rvmrc
24
24
 
25
25
  ## PROJECT::SPECIFIC
26
+ keys.json
data/ChangeLog CHANGED
@@ -1,3 +1,15 @@
1
+ 1.1.2 (2010-10-6)
2
+
3
+ * Added ability to perform OAuth authorization on behalf of the user.
4
+ * Specs now test authorization against actual Dropbox API server.
5
+
6
+ 1.1.1 (2010-09-22)
7
+
8
+ * http-proxy support added.
9
+ * Session now persists SSL attribute.
10
+ * Core extensions moved to a namespaced path to prevent conflicts.
11
+ * Minor bug fixes.
12
+
1
13
  1.1.0 (2010-05-27)
2
14
 
3
15
  * Added thumbnails API method.
data/README.rdoc CHANGED
@@ -75,6 +75,11 @@ account, and then upload a file to their Dropbox.
75
75
 
76
76
  == Testing Your Code
77
77
 
78
+ The gem is fully specced. Run specs with +rake spec+. Before doing so, you will
79
+ need to create a file called +keys.json+ in the project root containing your
80
+ Dropbox API key and secret, as well as the email and password for a Dropbox
81
+ account. See the +keys.json.example+ file to get started.
82
+
78
83
  fguillen has implemented a mock of the Dropbox API server:
79
84
  http://github.com/fguillen/DummyDropbox
80
85
 
data/Rakefile CHANGED
@@ -17,6 +17,7 @@ begin
17
17
  gem.add_runtime_dependency "oauth", ">= 0.3.6"
18
18
  gem.add_runtime_dependency "json", ">= 1.2.0"
19
19
  gem.add_runtime_dependency "multipart-post", ">= 1.0"
20
+ gem.add_runtime_dependency "mechanize", ">= 1.0.0"
20
21
  end
21
22
  Jeweler::GemcutterTasks.new
22
23
  Jeweler::RubyforgeTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.1
1
+ 1.1.2
data/dropbox.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{dropbox}
8
- s.version = "1.1.1"
8
+ s.version = "1.1.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Tim Morgan"]
12
- s.date = %q{2010-09-22}
12
+ s.date = %q{2010-10-06}
13
13
  s.description = %q{An easy-to-use client library for the official Dropbox API.}
14
14
  s.email = %q{dropbox@timothymorgan.info}
15
15
  s.extra_rdoc_files = [
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
26
26
  "Rakefile",
27
27
  "VERSION",
28
28
  "dropbox.gemspec",
29
+ "keys.json.example",
29
30
  "lib/dropbox.rb",
30
31
  "lib/dropbox/api.rb",
31
32
  "lib/dropbox/entry.rb",
@@ -72,17 +73,20 @@ Gem::Specification.new do |s|
72
73
  s.add_runtime_dependency(%q<oauth>, [">= 0.3.6"])
73
74
  s.add_runtime_dependency(%q<json>, [">= 1.2.0"])
74
75
  s.add_runtime_dependency(%q<multipart-post>, [">= 1.0"])
76
+ s.add_runtime_dependency(%q<mechanize>, [">= 1.0.0"])
75
77
  else
76
78
  s.add_dependency(%q<rspec>, [">= 1.2.9"])
77
79
  s.add_dependency(%q<oauth>, [">= 0.3.6"])
78
80
  s.add_dependency(%q<json>, [">= 1.2.0"])
79
81
  s.add_dependency(%q<multipart-post>, [">= 1.0"])
82
+ s.add_dependency(%q<mechanize>, [">= 1.0.0"])
80
83
  end
81
84
  else
82
85
  s.add_dependency(%q<rspec>, [">= 1.2.9"])
83
86
  s.add_dependency(%q<oauth>, [">= 0.3.6"])
84
87
  s.add_dependency(%q<json>, [">= 1.2.0"])
85
88
  s.add_dependency(%q<multipart-post>, [">= 1.0"])
89
+ s.add_dependency(%q<mechanize>, [">= 1.0.0"])
86
90
  end
87
91
  end
88
92
 
data/keys.json.example ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "key": "abc123456789012",
3
+ "secret": "abc123456789012",
4
+ "email": "my@email.com",
5
+ "password": "mypassword123"
6
+ }
@@ -1,6 +1,7 @@
1
1
  # Defines the Dropbox::Session class.
2
2
 
3
3
  require 'oauth'
4
+ require 'mechanize'
4
5
 
5
6
  module Dropbox
6
7
 
@@ -47,6 +48,11 @@ module Dropbox
47
48
 
48
49
  class Session
49
50
  include API
51
+
52
+ # The email of a Dropbox account to automatically authorize.
53
+ attr_accessor :authorizing_user
54
+ # The password of a Dropbox account to automatically authorize.
55
+ attr_accessor :authorizing_password
50
56
 
51
57
  # Begins the authorization process. Provide the OAuth key and secret of your
52
58
  # API account, assigned by Dropbox. This is the first step in the
@@ -55,9 +61,18 @@ module Dropbox
55
61
  # Options:
56
62
  #
57
63
  # +ssl+:: If true, uses SSL to connect to the Dropbox API server.
64
+ # +authorizing_user+:: The email of a Dropbox account to automatically
65
+ # authorize.
66
+ # +authorizing_password+:: The password of a Dropbox account to
67
+ # automatically authorize.
58
68
 
59
69
  def initialize(oauth_key, oauth_secret, options={})
60
70
  @ssl = options[:ssl].to_bool
71
+
72
+ # necessary for the automatic authorization in #authorize!
73
+ @authorizing_user = options[:authorizing_user] if options[:authorizing_user]
74
+ @authorizing_password = options[:authorizing_password] if options[:authorizing_password]
75
+
61
76
  @proxy = options[:proxy] || ENV["HTTP_PROXY"] || ENV["http_proxy"]
62
77
  @proxy = nil if options[:noproxy].to_bool
63
78
  @consumer = OAuth::Consumer.new(oauth_key, oauth_secret,
@@ -103,6 +118,32 @@ module Dropbox
103
118
  def authorized?
104
119
  @access_token.to_bool
105
120
  end
121
+
122
+ # Automatically complete the authorization step of the OAuth process. You
123
+ # must have provided the +authorizing_user+ and +authorizing_password+
124
+ # options. Raises a Dropbox::UnauthorizedError on failure.
125
+
126
+ def authorize!
127
+ begin
128
+ a = Mechanize.new
129
+ a.get(authorize_url) do |page|
130
+ login_form = page.form_with(:action => '/login')
131
+
132
+ login_form.login_email = @authorizing_user
133
+ login_form.login_password = @authorizing_password
134
+ auth_page = login_form.submit()
135
+
136
+ auth_form = auth_page.form_with(:action => 'authorize')
137
+ if auth_form
138
+ auth_button = auth_form.button_with(:value => "Allow")
139
+ auth_form.click_button
140
+ end
141
+ end
142
+ rescue OAuth::Unauthorized => e
143
+ raise Dropbox::UnauthorizedError
144
+ end
145
+ authorize
146
+ end
106
147
 
107
148
  # Serializes this object into a string that can then be recreated with the
108
149
  # Dropbox::Session.deserialize method.
@@ -114,7 +155,7 @@ module Dropbox
114
155
  [ @consumer.key, @consumer.secret, authorized?, @request_token.token, @request_token.secret, @ssl ].to_yaml
115
156
  end
116
157
  end
117
-
158
+
118
159
  # Deserializes an instance from a string created from the serialize method.
119
160
  # Returns the recreated instance.
120
161
 
@@ -128,7 +169,7 @@ module Dropbox
128
169
  else
129
170
  session.instance_variable_set :@request_token, OAuth::RequestToken.new(session.instance_variable_get(:@consumer), token, token_secret)
130
171
  end
131
-
172
+
132
173
  return session
133
174
  end
134
175
 
@@ -15,7 +15,7 @@ describe Dropbox::Session do
15
15
 
16
16
  Dropbox::Session.new(key, secret)
17
17
  end
18
-
18
+
19
19
  it "should use the SSL host if :ssl => true is given" do
20
20
  key = 'test_key'
21
21
  secret = 'test_secret'
@@ -29,7 +29,7 @@ describe Dropbox::Session do
29
29
 
30
30
  Dropbox::Session.new(key, secret, :ssl => true)
31
31
  end
32
-
32
+
33
33
  it "should create a new OAuth::Consumer" do
34
34
  key = 'test_key'
35
35
  secret = 'test_secret'
@@ -117,10 +117,6 @@ describe Dropbox::Session do
117
117
  end
118
118
  end
119
119
 
120
- describe "#authorized?" do
121
- #TODO this method remains opaque for purposes of testing
122
- end
123
-
124
120
  describe "#serialize" do
125
121
  before :each do
126
122
  @consumer_mock = mock("OAuth::Consumer")
@@ -138,7 +134,7 @@ describe Dropbox::Session do
138
134
 
139
135
  @session.serialize.should eql([ "consumer key", "consumer secret", false, "request token", "request token secret", false ].to_yaml)
140
136
  end
141
-
137
+
142
138
  it "should serialize the SSL setting" do
143
139
  @session = Dropbox::Session.new('foo', 'bar', :ssl => true)
144
140
  @consumer_mock.stub!(:key).and_return("consumer key")
@@ -148,34 +144,95 @@ describe Dropbox::Session do
148
144
 
149
145
  @session.serialize.should eql([ "consumer key", "consumer secret", false, "request token", "request token secret", true ].to_yaml)
150
146
  end
151
-
152
- it "should return the consumer key and secret and the access token and secret in YAML form if authorized" do
153
- pending "access token is opaque"
154
- end
155
147
  end
156
148
 
157
149
  describe ".deserialize" do
150
+ before :each do
151
+ @mock_session = mock('Dropbox::Session')
152
+ end
153
+
158
154
  it "should raise an error if an improper YAML is provided" do
159
155
  lambda { Dropbox::Session.deserialize([ 1, 2, 3].to_yaml) }.should raise_error(ArgumentError)
160
156
  end
161
157
 
162
158
  it "should return a properly initialized unauthorized instance" do
163
- mock_session = mock('Dropbox::Session')
164
- Dropbox::Session.should_receive(:new).once.with('key', 'secret', :ssl => true).and_return(mock_session)
165
-
166
- Dropbox::Session.deserialize([ 'key', 'secret', false, 'a', 'b', true ].to_yaml).should eql(mock_session)
159
+ Dropbox::Session.should_receive(:new).once.with('key', 'secret', :ssl => true).and_return(@mock_session)
160
+
161
+ Dropbox::Session.deserialize([ 'key', 'secret', false, 'a', 'b', true ].to_yaml).should eql(@mock_session)
167
162
  #TODO request token remains opaque for purposes of testing
168
163
  end
169
-
164
+
170
165
  it "should allow the SSL option to be left out" do
171
- mock_session = mock('Dropbox::Session')
172
- Dropbox::Session.should_receive(:new).once.with('key', 'secret', :ssl => nil).and_return(mock_session)
173
-
174
- Dropbox::Session.deserialize([ 'key', 'secret', false, 'a', 'b' ].to_yaml).should eql(mock_session)
166
+ Dropbox::Session.should_receive(:new).once.with('key', 'secret', :ssl => nil).and_return(@mock_session)
167
+
168
+ Dropbox::Session.deserialize([ 'key', 'secret', false, 'a', 'b' ].to_yaml).should eql(@mock_session)
169
+ end
170
+ end
171
+
172
+ describe "with Dropbox keys " do
173
+ before(:all) do
174
+ @keys = read_keys_file
175
+ end
176
+
177
+ def new_session
178
+ Dropbox::Session.new(@keys['key'], @keys['secret'], :authorizing_user => @keys['email'], :authorizing_password => @keys['password'])
179
+ end
180
+
181
+ describe "#authorized?" do
182
+ before(:each) do
183
+ @session = new_session
184
+ end
185
+
186
+ it "should be false for sessions that have not been authorized" do
187
+ @session.should_not be_authorized
188
+ end
189
+
190
+ it "should be true for sessions that have been authorized" do
191
+ @session.authorize!
192
+ @session.should be_authorized
193
+ end
194
+ end
195
+
196
+ describe "#authorize!" do
197
+ describe "with credentials" do
198
+ before(:each) do
199
+ @session = new_session
200
+ end
201
+
202
+ it "should not fail" do
203
+ lambda { @session.authorize! }.should_not raise_error
204
+ end
205
+
206
+ it "should return the result of #authorize" do
207
+ @session.should_receive(:authorize).and_return("winner!")
208
+ @session.authorize!.should == "winner!"
209
+ end
210
+ end
211
+
212
+ describe "with no credentials" do
213
+ it "should fail" do
214
+ @session = Dropbox::Session.new(@keys['key'], @keys['password'])
215
+ lambda { @session.authorize! }.should raise_error
216
+ end
217
+ end
218
+ end
219
+
220
+ describe ".deserialize" do
221
+ it "should return a properly initialized authorized instance" do
222
+ @session = new_session
223
+ @session.authorize!.should be_true
224
+ @session_clone = Dropbox::Session.deserialize(@session.serialize)
225
+
226
+ @session.serialize.should == @session_clone.serialize
227
+ end
175
228
  end
176
229
 
177
- it "should return a properly initialized authorized instance" do
178
- pending "access token remains opaque for purposes of testing"
230
+ describe "#serialize" do
231
+ it "should return the consumer key and secret and the access token and secret in YAML form if authorized" do
232
+ @session = new_session
233
+ @session.authorize!.should be_true
234
+ @session.serialize.should eql([ @keys['key'], @keys['secret'], true, @session.send(:access_token).token, @session.send(:access_token).secret, false ].to_yaml)
235
+ end
179
236
  end
180
237
  end
181
238
  end
data/spec/spec_helper.rb CHANGED
@@ -5,6 +5,22 @@ require 'dropbox.rb'
5
5
  require 'spec'
6
6
  require 'spec/autorun'
7
7
 
8
+ module ExternalKeysFileHelper
9
+ def read_keys_file
10
+ unless File.exist?('keys.json')
11
+ raise "Please add a keys.json file to the project directory containing your Dropbox API key and secret. See keys.json.example to get started."
12
+ end
13
+
14
+ keys_file_contents = open("keys.json", "r").read()
15
+ data = JSON.parse(keys_file_contents)
16
+ unless %w( key secret email password ).all? { |key| data.include? key }
17
+ raise "Your keys.json file does contain all the required information. See keys.json.example for more help."
18
+ end
19
+
20
+ data
21
+ end
22
+ end
23
+
8
24
  Spec::Runner.configure do |config|
9
-
25
+ config.include(ExternalKeysFileHelper)
10
26
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 1
7
7
  - 1
8
- - 1
9
- version: 1.1.1
8
+ - 2
9
+ version: 1.1.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Tim Morgan
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-09-22 00:00:00 -07:00
17
+ date: 2010-10-06 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -76,6 +76,21 @@ dependencies:
76
76
  version: "1.0"
77
77
  type: :runtime
78
78
  version_requirements: *id004
79
+ - !ruby/object:Gem::Dependency
80
+ name: mechanize
81
+ prerelease: false
82
+ requirement: &id005 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ segments:
88
+ - 1
89
+ - 0
90
+ - 0
91
+ version: 1.0.0
92
+ type: :runtime
93
+ version_requirements: *id005
79
94
  description: An easy-to-use client library for the official Dropbox API.
80
95
  email: dropbox@timothymorgan.info
81
96
  executables: []
@@ -95,6 +110,7 @@ files:
95
110
  - Rakefile
96
111
  - VERSION
97
112
  - dropbox.gemspec
113
+ - keys.json.example
98
114
  - lib/dropbox.rb
99
115
  - lib/dropbox/api.rb
100
116
  - lib/dropbox/entry.rb