cs210-gdata4ruby 0.1.5 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,4 +1,7 @@
1
+ <<<<<<< HEAD
1
2
  #=CHANGELOG
3
+ #==version 0.1.6
4
+ #* Save the 'S'-cookie and send it with future requests to avoid '302 Redirect' responses
2
5
  #==version 0.1.5
3
6
  #* Changed license to LGPLv3
4
7
  #==version 0.1.4
@@ -12,3 +15,22 @@
12
15
  #* Added additional common attributes, including content, published, updated and author info
13
16
  #==version 0.1.0
14
17
  #* Initial Version
18
+ =======
19
+ =CHANGELOG
20
+ ==version 0.2.0
21
+ * Implemented OAuth support (using the OAuth gem)
22
+ * This requires minor changes to how the Base & Service classes are called
23
+ ==version 0.1.5
24
+ * Changed license to LGPLv3
25
+ ==version 0.1.4
26
+ * Bugfix for GeoRSS and GML namespaces
27
+ ==version 0.1.3
28
+ * Added support for Geo/GeoRSS namespaces in base gdata object
29
+ * Added support for Ruby 1.9
30
+ ==version 0.1.2
31
+ * Added better support for 'default' users in AccessRule
32
+ ==version 0.1.1
33
+ * Added additional common attributes, including content, published, updated and author info
34
+ ==version 0.1.0
35
+ * Initial Version
36
+ >>>>>>> edave/master
data/README.md CHANGED
@@ -1,45 +1,71 @@
1
1
  #GData4Ruby
2
2
 
3
- ##Introduction
3
+ ## Introduction
4
4
 
5
- GData4Ruby is a full featured wrapper for the Google Data base API. GData4Ruby provides the ability
6
- to authenticate with GData using the ClientLogin method. The package also includes a base gdata object
7
- that can be subclassed to provide basic CRUD functions for all Google API service objects. Additionally,
8
- a basic ACL object is included for interacting with ACL feeds and setting access rules.
5
+ GData4Ruby is a full featured wrapper for the Google Data base API. GData4Ruby provides the ability to authenticate with GData using the ClientLogin method. The package also includes a base gdata object that can be subclassed to provide basic CRUD functions for all Google API service objects. Additionally, a basic ACL object is included for interacting with ACL feeds and setting access rules.
9
6
 
10
- ##Author and Contact Information
7
+ ## Author and Contact Information
11
8
 
12
- GData4Ruby was created and is maintained by [Mike Reich](mailto:mike@seabourneconsulting.com])
13
- and is licenses under the LGPL v3. You can find the text of the LGPL
14
- here: http://www.gnu.org/licenses/lgpl.html. Feel free to use and update, but be sure to contribute your
15
- code back to the project and attribute as required by the license.
9
+ GData4Ruby was created and is maintained by {Mike Reich}[mailto:mike@seabourneconsulting.com] and is licenses under the LGPL v3. You can find the text of the LGPL here: http://www.gnu.org/licenses/lgpl.html. Feel free to use and update, but be sure to contribute your code back to the project and attribute as required by the license.
16
10
 
17
- ##Website
11
+ OAuth support was added by [edave](https://github.com/edave/)
18
12
 
19
- [http://cookingandcoding.com/gdata4ruby/](http://cookingandcoding.com/gdata4ruby/)
13
+ ### Website
20
14
 
21
- ##Description
15
+ http://cookingandcoding.com/gdata4ruby/
22
16
 
23
- GData4Ruby has three major components: the service, the GData object and the AccessRule object. Each service
24
- represents a google account, and includes a username (email) and a password. You can use the GData service
25
- to authenticate either a google account or a google apps account.
17
+ ## Description
18
+
19
+ GData4Ruby has three major components: the service, the GData object and the AccessRule object. Each service represents a google account, and includes a username (email) and a password. You can use the GData service to authenticate either a google account or a google apps account. There are currently two types of services, Service, and OAuthService.
20
+
21
+ Service uses Google's older [AuthSub](http://code.google.com/apis/accounts/docs/AuthSub.html) authentication mechanism, which is easier to setup, but requires you always know the username/password. (called Service to maintain backwards compatibility, but don't be confused, the base "Service" class is named Base)
22
+
23
+ OAuthService uses Google's newest authentication mechanism, [OAuth](http://code.google.com/apis/accounts/docs/OAuth.html), which is an OpenID-esque login system.
24
+
25
+ See Google's [Getting Started](http://code.google.com/apis/accounts/docs/GettingStarted.html) for more info on which mechanism is best for you. In general, it will likely be easiest to experiment with GData4Ruby using AuthSub and then switch to OAuth for any actual usage in your web app, etc.
26
26
 
27
27
  The GData object provides a base class for interacting with Google API objects, i.e. Documents, Events, etc. The GData object contains common attributes present in all Google API objects, and provides interfaces for basic CRUD functions. This class is meant to be subclassed.
28
28
 
29
29
  The AccessRule object provides a base class for interacting with Google Access Control Lists. ACLs provide the main permissions mechanism for most Google API services.
30
30
 
31
- ##Examples
31
+ ## Examples
32
32
 
33
33
  Below are some common usage examples. For more examples, check the documentation.
34
34
 
35
- ###Service
35
+ ### Service
36
36
 
37
37
  1. Authenticate
38
-
39
38
  service = Service.new
40
- service.authenticate("user@gmail.com", "password", "cl")
39
+ service.authenticate({:username => "user@gmail.com", :password => "password", :service => "cl"})
41
40
 
42
41
  2. Authenticate with a specified GData version
42
+ service = Service.new({:gdata_version => '3.0'})
43
+ service.authenticate({:username => "user@gmail.com", :password => "password", :service => "cl"})
44
+
45
+ ### OAuthService
46
+
47
+ You will need an OAuth Token for authenticating for any given user. If you are using Rails, [OAuth Plugin](https://github.com/pelle/oauth-plugin) makes this fairly easy for users to grant access to your application and generate [OAuth Tokens](http://code.google.com/p/oauth-plugin/wiki/AccessToken).
48
+
49
+ Once you have a token, authenticating is simple:
50
+
51
+ service = OAuthService.new
52
+ my_oauth_token = OAuth::AccessToken.new() # you will need to generate your own OAuth::Token
53
+ service.authenticate({:access_token=>my_oauth_token})
54
+
55
+
56
+
57
+ ## Base Options
58
+
59
+ GData4Ruby supports several options which are passed to any service (Base, Service, OAuthService) upon initialization using a hash
60
+
61
+ Enable SSL:
62
+
63
+ my_generic_service = Service.new({:use_ssl => true})
64
+
65
+ Enable Debug Logging:
66
+
67
+ my_generic_service = Service.new({:debug => true})
68
+
69
+ Disable checking whether the objects are publicly accessibly. This can significantly speed up the service, but also leaves you at risk of trying write to Google services which you do not have privileges. In many cases, you can disable this option.
43
70
 
44
- service = Service.new({:gdata_version => '3.0'})
45
- service.authenticate("user@gmail.com", "password", "cl")
71
+ my_generic_service = Service.new({:check_public => false})
@@ -1 +1,2 @@
1
1
  require "gdata4ruby/service"
2
+ require "gdata4ruby/oauth_service"
@@ -65,11 +65,12 @@ module GData4Ruby
65
65
  #the Service subclass.
66
66
 
67
67
  class Base
68
- AUTH_URL = "https://www.google.com/accounts/ClientLogin"
68
+ @@auth_url = "https://www.google.com/accounts/ClientLogin"
69
69
  @proxy_info = nil
70
70
  @auth_token = nil
71
71
  @debug = false
72
72
  @gdata_version = '2.1'
73
+ @session_cookie = nil
73
74
 
74
75
  #Contains the ProxyInfo object for using a proxy server
75
76
  attr_accessor :proxy_info
@@ -80,27 +81,82 @@ module GData4Ruby
80
81
  #The GData version used by the service
81
82
  attr_accessor :gdata_version
82
83
 
84
+ # Will have the service use https instead of http
85
+ attr_accessor :use_ssl
86
+
83
87
  #Optionally, pass a hash of attributes to populate the class. If you want to use a GData version
84
88
  #other than the default (2.1), pass a key/value pair, i.e. {:gdata_version => '1.0'}
85
89
  def initialize(attributes = {})
86
- @gdata_version = attributes[:gdata_version] ? attributes[:gdata_version] : '2.1'
90
+ attributes.each do |key, value|
91
+ if self.respond_to?("#{key}=")
92
+ self.send("#{key}=", value)
93
+ end
94
+ end
95
+ @gdata_version ||= '2.1'
96
+ @use_ssl ||= false
97
+ @debug ||= false
87
98
  end
88
99
 
100
+ # Provides a mechanism for your service to receive credentials and authenticate
101
+ def authenticate(options = {})
102
+
103
+ end
104
+
105
+ # Allows a user to revive the authentication (connection)
106
+ def reauthenticate(options = {})
107
+
108
+ end
109
+
110
+ # Is the service successfully authenticated and connected to google?
111
+ def authenticated?
112
+ return false
113
+ end
114
+
115
+ def log(string)
116
+ puts string if self.debug
117
+ end
118
+
119
+ def create_url(path)
120
+ return http_protocol + path
121
+ end
122
+
89
123
  #Sends a request to the Google Data System. Accepts a valid Request object, and returns a
90
124
  #HTTPResult class.
91
125
  def send_request(request)
92
126
  raise ArgumentError 'Request must be a GData4Ruby::Request object' if not request.is_a?Request
93
- puts "sending #{request.type} to url = #{request.url.to_s}" if @debug
127
+ log("sending #{request.type} to url = #{request.url.to_s}")
94
128
  do_request(request)
95
129
  end
96
130
 
97
131
  private
98
132
 
133
+ def set_protocol!(request)
134
+ uri = request.url
135
+ if uri.scheme != protocol
136
+ request.url = URI.parse(uri.to_s.sub(uri.scheme, protocol))
137
+ # values = uri.select(*uri.component)
138
+ # keys = uri.component
139
+ # components_hash = {}
140
+ # # Build a hash where the keys are from keys[] and values are from values[]
141
+ # keys.zip(values) {|a,b| components_hash[a] = b }
142
+ # components_hash[:scheme] = protocol
143
+ # request.url = case protocol
144
+ # when 'https'
145
+ # URI::HTTPS.build(components_hash)
146
+ # when 'http'
147
+ # URI::HTTP.build(components_hash)
148
+ # end
149
+ end
150
+ end
151
+
99
152
  def do_request(request)
100
153
  ret = nil
101
154
  add_auth_header(request)
155
+ # Add the session cookie if available
156
+ request.headers.merge!({'Cookie' => @session_cookie}) if @session_cookie
157
+ set_protocol!(request)
102
158
  http = get_http_object(request.url)
103
- puts "Sending request\nHeader: #{request.headers.inspect.to_s}\nContent: #{request.content.to_s}\n" if @debug
159
+ log("Sending request\nHeader: #{request.headers.inspect.to_s}\nContent: #{request.content.to_s}\n")
104
160
  http.start do |ht|
105
161
  ret = case request.type
106
162
  when :get
@@ -113,19 +169,31 @@ module GData4Ruby
113
169
  ht.delete(request.url.to_s, request.headers)
114
170
  end
115
171
  end
116
-
172
+
173
+ if @debug
174
+ puts "Response code: #{ret.code}"
175
+ puts "Headers: \n"
176
+ ret.each { |h, v| puts "#{h}:#{v}" }
177
+ puts "Body: \n" + ret.read_body
178
+ end
179
+
180
+ # Save the session cookie if set
181
+ ret.get_fields('set-cookie').to_a.each do |header|
182
+ cookie = header.split(';').first
183
+ @session_cookie = cookie if cookie =~ /^S=.+/
184
+ end
185
+
117
186
  while ret.is_a?(Net::HTTPRedirection)
118
- puts "Redirect received, resending request" if @debug
187
+ log("Redirect received, resending request")
119
188
  request.parameters = nil
120
189
  request.url = ret['location']
121
- puts "sending #{request.type} to url = #{request.url.to_s}" if @debug
190
+ log("sending #{request.type} to url = #{request.url.to_s}")
122
191
  ret = do_request(request)
123
192
  end
124
193
  if not ret.is_a?(Net::HTTPSuccess)
125
- puts "invalid response received: "+ret.code if @debug
194
+ log("invalid response received: "+ret.code)
126
195
  raise HTTPRequestFailed, ret.body
127
196
  end
128
- puts "20x response received\nResponse: \n"+ret.read_body if @debug
129
197
  return ret
130
198
  end
131
199
 
@@ -137,7 +205,7 @@ module GData4Ruby
137
205
  end
138
206
  if location.scheme == 'https'
139
207
  #fixed http/http misnaming via JohnMetta
140
- puts "SSL True" if @debug
208
+ log("SSL True")
141
209
  http.use_ssl = true
142
210
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
143
211
  end
@@ -154,5 +222,18 @@ module GData4Ruby
154
222
  end
155
223
  end
156
224
  end
225
+
226
+ protected
227
+ def protocol
228
+ ssl_suffix = ""
229
+ ssl_suffix = "s" if use_ssl
230
+ return "http#{ssl_suffix}"
231
+ end
232
+ def http_protocol
233
+ ssl_suffix = ""
234
+ ssl_suffix = "s" if use_ssl
235
+ return "http#{ssl_suffix}://"
236
+ end
237
+
157
238
  end
158
239
  end
@@ -73,6 +73,9 @@ module GData4Ruby
73
73
  #The kind (type) of the object
74
74
  attr_reader :kind
75
75
 
76
+ #Used for debugging
77
+ attr_accessor :debug
78
+
76
79
  #Indicates whether the object exists on the Google servers, i.e. has been created/saved.
77
80
  def exists?
78
81
  return @exists
@@ -89,7 +92,9 @@ module GData4Ruby
89
92
  @categories = @feed_links = []
90
93
  @include_etag = true
91
94
  attributes.each do |key, value|
92
- self.send("#{key}=", value)
95
+ if self.respond_to?("#{key}=")
96
+ self.send("#{key}=", value)
97
+ end
93
98
  end
94
99
  end
95
100
 
@@ -104,14 +109,16 @@ module GData4Ruby
104
109
  @etag = xml.root.attributes['etag'] if xml.root.attributes['etag']
105
110
  case ele.name
106
111
  when "id"
107
- puts 'setting id' if service.debug
108
112
  @feed_uri = ele.text
113
+ log("ID: #{@feed_uri}")
109
114
  when 'content'
110
115
  @content_uri = ele.attributes['src'] if ele.attributes['src']
116
+ log("Content URI: #{@content_uri}")
111
117
  when 'resourceId'
112
118
  @id = ele.text
113
119
  when 'title'
114
120
  @title = ele.text
121
+ log("Title: #{@title}")
115
122
  when 'category'
116
123
  @categories << {:label => ele.attributes['label'],
117
124
  :scheme => ele.attributes['scheme'],
@@ -160,6 +167,11 @@ module GData4Ruby
160
167
  return true
161
168
  end
162
169
 
170
+
171
+ def log(string)
172
+ puts string if debug
173
+ end
174
+
163
175
  #Creates the object. This must be overridden in a subclass, as the feed url for creating new
164
176
  #objects/entries is service dependent. In other words, each google service uses a different
165
177
  #URI for saving new objects.
@@ -194,4 +206,4 @@ module GData4Ruby
194
206
  xml.to_s
195
207
  end
196
208
  end
197
- end
209
+ end
@@ -0,0 +1,95 @@
1
+ # Author:: David Pitman (ui-design@vestaldesign.com )
2
+ # Copyright:: Copyright (C) 2010 David Pitman
3
+ # License:: LGPL v2.1
4
+ #--
5
+ # Licensed under the Lesser General Public License (GPL), Version 2.1 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.gnu.org/licenses/lgpl-2.1.txt
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ #
15
+ # Feel free to use and update, but be sure to contribute your
16
+ # code back to the project and attribute as required by the license.
17
+ #++
18
+ require 'gdata4ruby/base'
19
+
20
+ module GData4Ruby
21
+ #The service class is the main handler for all direct interactions with the
22
+ #Google Data API.
23
+
24
+ class OAuthService < Base
25
+ #Convenience attribute contains the currently OAuth access token
26
+ attr_reader :access_token
27
+
28
+ #Accepts an optional attributes hash for initialization values, most likely :gdata_version
29
+ def initialize(attributes = {})
30
+ super(attributes)
31
+ attributes.each do |key, value|
32
+ if self.respond_to?("#{key}=")
33
+ self.send("#{key}=", value)
34
+ end
35
+ end
36
+ end
37
+
38
+ # The method is a generic hash to allow subclasses to easily receive args for their own type of authentication
39
+ # In this case, we're using an OAuth AccessToken - http://oauth.rubyforge.org/rdoc/classes/OAuth/AccessToken.html
40
+ def authenticate(options = {})
41
+ @access_token = options[:access_token]
42
+ end
43
+
44
+ def reauthenticate(options = {})
45
+ @access_token ||= options[:access_token]
46
+ end
47
+
48
+
49
+ def authenticated?
50
+ return (@access_token != nil)
51
+ end
52
+
53
+ private
54
+
55
+ def do_request(request)
56
+ log("Sending request\nHeader: #{request.headers.inspect.to_s}\nContent: #{request.content.to_s}\n")
57
+ set_protocol!(request)
58
+ ret = case request.type
59
+ when :get
60
+ @access_token.get(request.url.to_s, {}, request.headers)
61
+ when :post
62
+ @access_token.post(request.url.to_s, request.content, request.headers)
63
+ when :put
64
+ @access_token.put(request.url.to_s, request.content, request.headers)
65
+ when :delete
66
+ @access_token.delete(request.url.to_s, {}, request.headers)
67
+ end
68
+
69
+ while ret.is_a?(Net::HTTPRedirection)
70
+ log("Redirect received, resending request")
71
+ request.parameters = nil
72
+ request.url = ret['location']
73
+ log("sending #{request.type} to url = #{request.url.to_s}")
74
+ ret = do_request(request)
75
+ end
76
+ if not ret.is_a?(Net::HTTPSuccess)
77
+ log("invalid response received: "+ret.code)
78
+ raise HTTPRequestFailed, ret.body
79
+ end
80
+ log("20x response received\nResponse: \n"+ret.read_body)
81
+ return ret
82
+ end
83
+
84
+ # Not used in OAuth implementation...
85
+ def get_http_object(location)
86
+ return nil
87
+ end
88
+
89
+ # Not used in OAuth implementation...
90
+ def add_auth_header(request)
91
+ return nil
92
+ end
93
+
94
+ end
95
+ end
@@ -32,17 +32,24 @@ module GData4Ruby
32
32
  def initialize(attributes = {})
33
33
  super(attributes)
34
34
  attributes.each do |key, value|
35
- self.send("#{key}=", value)
35
+ if self.respond_to?("#{key}=")
36
+ self.send("#{key}=", value)
37
+ end
36
38
  end
37
39
  end
38
40
 
39
41
  # The authenticate method passes the username and password to google servers.
40
42
  # If authentication succeeds, returns true, otherwise raises the AuthenticationFailed error.
41
43
  # Thanks to David King and Scott Taylor for Ruby 1.9 fix.
42
- def authenticate(username, password, service)
44
+ def authenticate(options = {})
45
+ username = options[:username]
46
+ password = options[:password]
47
+ service = options[:service]
43
48
  @auth_token = nil
44
49
  ret = nil
45
- ret = send_request(Request.new(:post, AUTH_URL, "Email=#{username}&Passwd=#{password}&source=GCal4Ruby&service=#{service}&accountType=HOSTED_OR_GOOGLE"))
50
+ auth_args = "Email=#{username}&Passwd=#{password}&source=GCal4Ruby&service=#{service}&accountType=HOSTED_OR_GOOGLE"
51
+ log(auth_args)
52
+ ret = send_request(Request.new(:post, @@auth_url, auth_args))
46
53
  if ret.class == Net::HTTPOK
47
54
  body = ret.read_body
48
55
  lines = body.send(body.respond_to?(:lines) ? :lines : :to_s).to_a
@@ -51,8 +58,20 @@ module GData4Ruby
51
58
  @password = password
52
59
  return true
53
60
  else
61
+ @auth_token = nil
54
62
  raise AuthenticationFailed
55
63
  end
56
64
  end
65
+
66
+ def reauthenticate(options = {})
67
+ options[:username] ||= @account
68
+ options[:password] ||= @password
69
+ authenticate(options)
70
+ end
71
+
72
+ def authenticated?
73
+ log("Authenticated: #{@auth_token}")
74
+ return (@auth_token != nil)
75
+ end
57
76
  end
58
77
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: cs210-gdata4ruby
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.5
5
+ version: 0.2.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Mike Reich
@@ -10,10 +10,19 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-04-13 00:00:00 -07:00
14
- default_executable:
15
- dependencies: []
16
-
13
+ date: 2011-04-29 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: oauth2
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.4.1
24
+ type: :runtime
25
+ version_requirements: *id001
17
26
  description: A full featured wrapper for interacting with the base Google Data API, including authentication and basic object handling
18
27
  email: mike@seabourneconsulting.com
19
28
  executables: []
@@ -28,12 +37,12 @@ files:
28
37
  - lib/gdata4ruby.rb
29
38
  - lib/gdata4ruby/base.rb
30
39
  - lib/gdata4ruby/service.rb
40
+ - lib/gdata4ruby/oauth_service.rb
31
41
  - lib/gdata4ruby/request.rb
32
42
  - lib/gdata4ruby/gdata_object.rb
33
43
  - lib/gdata4ruby/utils/utils.rb
34
44
  - lib/gdata4ruby/acl/access_rule.rb
35
45
  - test/unit.rb
36
- has_rdoc: true
37
46
  homepage: http://cookingandcoding.com/gdata4ruby/
38
47
  licenses: []
39
48
 
@@ -57,7 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
57
66
  requirements: []
58
67
 
59
68
  rubyforge_project: gdata4ruby
60
- rubygems_version: 1.6.1
69
+ rubygems_version: 1.7.2
61
70
  signing_key:
62
71
  specification_version: 3
63
72
  summary: A full featured wrapper for interacting with the base Google Data API