gdata2 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/CREDITS ADDED
@@ -0,0 +1,3 @@
1
+
2
+ This code began as a project by Jérôme Bousquié as a google code project:
3
+ http://code.google.com/p/gdatav2rubyclientlib/.
data/History.txt ADDED
File without changes
data/Manifest.txt ADDED
@@ -0,0 +1,15 @@
1
+ CREDITS
2
+ History.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ TODO
7
+ bin/config.yml
8
+ bin/sync-google-apps
9
+ gdata2.gemspec
10
+ lib/gdata.rb
11
+ lib/gdata/apps.rb
12
+ lib/gdata/apps/email.rb
13
+ lib/gdata/apps/provisioning.rb
14
+ lib/gdata/messages.rb
15
+ scripts/test.rb
data/README.txt ADDED
@@ -0,0 +1,70 @@
1
+ = gdata2
2
+
3
+ == DESCRIPTION:
4
+
5
+ gdata2 is a Ruby wrapper around the Google Data API's.
6
+
7
+ == FEATURES:
8
+
9
+ * Provides simple to use ruby-like api to Google Data API's.
10
+
11
+ == INSTALL:
12
+
13
+ === Ruby Gem:
14
+
15
+ sudo gem install gdata2
16
+
17
+ === Manual Download:
18
+
19
+ Install ruby-net-ldap gem
20
+ Install sequel gem
21
+ Install sqlite3-ruby gem
22
+ Download the latest release from <URL>
23
+
24
+ === Git:
25
+
26
+ You can check out the git repository at http://github.com/<URL>
27
+
28
+ == TODO:
29
+
30
+ #Unfinished
31
+ * Document the configuration yml for gapps-provision
32
+ * Set timestamps on the resulting database
33
+ * Un neuter the creation queue
34
+ * Un neuter the alteration queue
35
+ * enter code for the creation of admin users from the gapps-provision
36
+ file?
37
+ * inserts into the google alias table appears to not check and see if
38
+ they already exist
39
+
40
+ Adding more Google Data apis to the bundle.
41
+ # Apps APIs
42
+ * Provisioning
43
+ * Email Settings
44
+ * Calendar Data
45
+ * Reporting
46
+ # Data APIs
47
+ * Contacts Data
48
+ * Documents List Data
49
+ * Spreadsheets Data'
50
+
51
+ == SYNOPSIS:
52
+
53
+ TODO: write new
54
+
55
+ == LICENSE:
56
+
57
+ Copyright 2008-2009 Jérôme Bousquié
58
+ Copyright 2009 Montana State University
59
+
60
+ Licensed under the Apache License, Version 2.0 (the "License");
61
+ you may not use this file except in compliance with the License.
62
+ You may obtain a copy of the License at
63
+
64
+ http://www.apache.org/licenses/LICENSE-2.0
65
+
66
+ Unless required by applicable law or agreed to in writing, software
67
+ distributed under the License is distributed on an "AS IS" BASIS,
68
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
69
+ See the License for the specific language governing permissions and
70
+ limitations under the License.
data/Rakefile ADDED
@@ -0,0 +1,62 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require "spec/rake/spectask"
6
+ require './lib/gdata'
7
+
8
+ class Hoe
9
+ def extra_deps; @extra_deps.reject { |x| Array(x).first == "hoe" } end
10
+ end # copied from the Rakefile of the sup project
11
+
12
+ Hoe.new('gdata2', "0.1") do |p|
13
+ p.rubyforge_name = 'gdata2'
14
+ p.author = 'Ivan R. Judson'
15
+ p.email = 'ivan.judson@montana.edu'
16
+ p.summary = 'Ruby Wrapper for the Google Data APIs'
17
+ p.description = p.paragraphs_of('README.txt', 2..3).join("\n\n")
18
+ p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
19
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
20
+ p.remote_rdoc_dir = ''
21
+ end
22
+
23
+
24
+ RDOC_OPTS = [
25
+ '--quiet',
26
+ '--title', 'gdata2 APIs',
27
+ '--main', 'README.txt',
28
+ '--charset', 'utf-8',
29
+ '--inline-source',
30
+ '--tab-width', '2',
31
+ '--line-numbers',
32
+ ]
33
+
34
+ Rake::RDocTask.new do |rdoc|
35
+ rdoc.rdoc_dir = 'doc/'
36
+ rdoc.options = RDOC_OPTS
37
+ rdoc.main = "README.txt"
38
+ rdoc.rdoc_files.add [
39
+ 'LICENSE.txt',
40
+ 'README.txt',
41
+ 'History.txt',
42
+ 'lib/**/*.rb'
43
+ ]
44
+ end
45
+
46
+ # desc "Run all specs"
47
+ # Spec::Rake::SpecTask.new do |t|
48
+ # t.spec_files = FileList["spec/**/*_spec.rb"]
49
+ # t.spec_opts = ["--options", "spec/spec.opts"]
50
+ # end
51
+ #
52
+ # desc "Run all specs and get coverage statistics"
53
+ # Spec::Rake::SpecTask.new('spec:rcov') do |t|
54
+ # t.spec_files = FileList["spec/**/*_spec.rb"]
55
+ # t.rcov = true
56
+ # t.spec_opts = ["--options", "spec/spec.opts"]
57
+ # end
58
+ #
59
+ # Rake::Task[:default].prerequisites.clear
60
+ # task :default => :spec
61
+
62
+ # vim: syntax=Ruby
data/TODO ADDED
@@ -0,0 +1,12 @@
1
+ TODO List
2
+ ===========================
3
+ Adding more Google Data apis to the bundle.
4
+ # Apps APIs
5
+ * Provisioning
6
+ * Email Settings
7
+ * Calendar Data
8
+ * Reporting
9
+ # Data APIs
10
+ * Contacts Data
11
+ * Documents List Data
12
+ * Spreadsheets Data'
data/gdata2.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{gdata2}
3
+ s.version = "0.1"
4
+ s.authors = ["Jérôme Bousquié", "Ivan R. Judson"]
5
+ s.email = "ivan.judson@montana.edu"
6
+ s.date = %q{2009-02-20}
7
+ s.homepage = ""
8
+ s.summary = "Ruby wrapper for Google Data API's"
9
+ s.description = "gdata2 is a ruby wrapper for the google data apis"
10
+
11
+ s.has_rdoc = true
12
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
13
+ s.rdoc_options = ["--main", "README.txt"]
14
+ s.files = ["CREDITS", "History.txt", "Manifest.txt", "README.txt",
15
+ "Rakefile", "TODO", "gdata2.gemspec", "lib/gdata.rb",
16
+ "lib/gdata/apps/provisioning.rb"]
17
+ s.require_paths = ["lib"]
18
+ s.rubyforge_project = "gdata2"
19
+ s.rubygems_version = "1.3.1"
20
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 2
25
+
26
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
27
+ s.add_development_dependency(%q<hoe>, [">= 1.8.3"])
28
+ else
29
+ s.add_dependency(%q<hoe>, [">= 1.8.3"])
30
+ end
31
+ else
32
+ s.add_dependency(%q<hoe>, [">= 1.8.3"])
33
+ end
34
+ end
data/lib/gdata.rb ADDED
@@ -0,0 +1,58 @@
1
+ $:.unshift(File.expand_path(File.dirname(__FILE__))) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ module GData #:nodoc:
5
+ require 'net/https'
6
+ require 'cgi'
7
+
8
+ class Connection
9
+ attr_reader :http_connection
10
+
11
+ # Establishes SSL connection to Google host
12
+ def initialize(host, port, proxy=nil, proxy_port=nil, proxy_user=nil, proxy_passwd=nil)
13
+ conn = Net::HTTP.new(host, port, proxy, proxy_port, proxy_user, proxy_passwd)
14
+ conn.use_ssl = true
15
+ conn.verify_mode = OpenSSL::SSL::VERIFY_PEER
16
+ conn.verify_mode = OpenSSL::SSL::VERIFY_NONE
17
+ store = OpenSSL::X509::Store.new
18
+ store.set_default_paths
19
+ conn.cert_store = store
20
+ conn.start
21
+ @http_connection = conn
22
+ end
23
+
24
+ # Performs the http request and returns the http response
25
+ def perform(method, path='', body=nil, header=nil)
26
+ backoff_factor = 2
27
+ resp = nil
28
+ while resp.nil?
29
+ begin
30
+ req = Net::HTTPGenericRequest.new(method, ! body.nil?, true, path)
31
+ req['Content-Type'] = header['Content-Type'] if header['Content-Type']
32
+ req['Authorization'] = header['Authorization'] if header['Authorization']
33
+ req['Content-length'] = body.length.to_s if body
34
+ resp = @http_connection.request(req, body)
35
+ rescue Timeout::Error
36
+ retry
37
+ rescue GData::GDataError => e
38
+ if e.code == "503"
39
+ resp = nil
40
+ sleep(backoff_factor)
41
+ backoff_factor *= backoff_factor
42
+ else
43
+ return e
44
+ end
45
+ rescue Errno::EPIPE
46
+ retry
47
+ rescue EOFError
48
+ end
49
+ end
50
+
51
+ return resp
52
+ end
53
+ end
54
+
55
+ class GDataError < RuntimeError
56
+ attr_accessor :code, :input, :reason
57
+ end
58
+ end
@@ -0,0 +1,437 @@
1
+ $:.unshift(File.expand_path(File.dirname(__FILE__))) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'messages'
5
+
6
+ module GData #:nodoc:
7
+ module Apps #:nodoc:
8
+ # =Administrative object for accessing your domain
9
+ # Examples
10
+ #
11
+ # adminuser = "root@mydomain.com"
12
+ # password = "PaSsWo4d!"
13
+ # gapp = GApps.new('root@mydomain.com','PaSsWoRd')
14
+ # myapps = Provisioning.new(gapp)
15
+ # (see examples in ProvisioningApi.new documentation for handling proxies)
16
+ #
17
+ # new_user = myapps.create_user("jsmith", "john", "smith", "secret", nil, "2048")
18
+ # puts new_user.family_name
19
+ # puts new_user.given_name
20
+ #
21
+ # Want to update a user ?
22
+ #
23
+ # user = myapps.retrieve_user('jsmith')
24
+ # user_updated = myapps.update_user(user.username, user.given_name, user.family_name, nil, nil, "true")
25
+ #
26
+ # Want to add an alias or nickname ?
27
+ #
28
+ # new_nickname = myapps.create_nickname("jsmith", "john.smith")
29
+ #
30
+ # Want to handle errors ?
31
+ #
32
+ # begin
33
+ # user = myapps.retrieve_user('noone')
34
+ # puts "givenName : "+user.given_name, "familyName : "+user.family_name, "username : "+user.username"
35
+ # puts "admin ? : "+user.admin
36
+ # rescue GDataError => e
37
+ # puts "errorcode = " +e.code, "input : "+e.input, "reason : "+e.reason
38
+ # end
39
+ #
40
+ # Group ?
41
+ #
42
+ # new_list = myapps.create_group("sale-dep")
43
+ # new_address = myapps.add_to_group("sale-dep", "bibi@ruby-forge.org")
44
+ #
45
+
46
+ class Provisioning
47
+
48
+ @@google_host = 'apps-apis.google.com'
49
+
50
+ # Creates a new Provisioning object
51
+ #
52
+ # apps: Google Apps Object (GData::GApps)
53
+ #
54
+ #
55
+ # Examples :
56
+ # standard : no proxy
57
+ # gapp = GApps.new('root@mydomain.com','PaSsWoRd')
58
+ # myapps = Provisioning.new(gapp)
59
+ # proxy :
60
+ # gapp = GApps.new('root@mydomain.com','PaSsWoRd','domain.proxy.com',8080)
61
+ # myapps = Provisioning.new(gapp)
62
+ # authenticated proxy :
63
+ # gapp = GApps.new('root@mydomain.com','PaSsWoRd','domain.proxy.com',8080,'foo','bAr')
64
+ # myapps = ProvisioningApi.new(gapp)
65
+ #
66
+ def initialize(apps)
67
+ @apps = apps
68
+ setup_actions()
69
+ end
70
+
71
+ # Creates an account in your domain, returns a UserEntry instance
72
+ # params :
73
+ # username, given_name, family_name and password are required
74
+ # passwd_hash_function (optional) : nil (default) or "SHA-1"
75
+ # quota (optional) : nil (default) or integer for limit in MB
76
+ # ex :
77
+ # gapp = GApps.new('root@mydomain.com','PaSsWoRd')
78
+ # myapps = ProvisioningApi.new(gapp)
79
+ # user = myapps.create('jsmith', 'John', 'Smith', 'p455wD')
80
+ #
81
+ # By default, a new user must change his password at first login. Please use update_user if you want to change this just after the creation.
82
+ def create_user(username, given_name, family_name, password, passwd_hash_function=nil, quota=nil)
83
+ msg = ProvisioningMessage.new
84
+ msg.about_login(username,password,passwd_hash_function,"false","false", "true")
85
+ msg.about_name(family_name, given_name)
86
+ msg.about_quota(quota.to_s) if quota
87
+ response = @apps.request(:user_create,nil, msg.to_s)
88
+ #user_entry = UserEntry.new(response.elements["entry"])
89
+ end
90
+
91
+
92
+ # Returns a UserEntry instance from a username
93
+ # ex :
94
+ # gapp = GApps.new('root@mydomain.com','PaSsWoRd')
95
+ # myapps = ProvisioningApi.new(gapp)
96
+ # user = myapps.retrieve_user('jsmith')
97
+ # puts "givenName : "+user.given_name
98
+ # puts "familyName : "+user.family_name
99
+ def retrieve_user(username)
100
+ xml_response = @apps.request(:user_retrieve, username)
101
+ if xml_response.respond_to? :elements
102
+ user_entry = UserEntry.new(xml_response.elements["entry"])
103
+ end
104
+ end
105
+
106
+ # Returns a UserEntry array populated with all the users in the domain. May take a while depending on the number of users in your domain.
107
+ # ex :
108
+ # gapp = GApps.new('root@mydomain.com','PaSsWoRd')
109
+ # myapps = ProvisioningApi.new(gapp)
110
+ # list= myapps.retrieve_all_users
111
+ # list.each{ |user| puts user.username}
112
+ # puts 'nb users : ',list.size
113
+ def retrieve_all_users
114
+ response = @apps.request(:user_retrieve_all)
115
+ user_feed = Feed.new(response.elements["feed"], UserEntry)
116
+ user_feed = add_next_feeds(user_feed, response, UserEntry)
117
+ end
118
+
119
+ # Returns a UserEntry array populated with 100 users, starting from a username
120
+ # ex :
121
+ # gapp = GApps.new('root@mydomain.com','PaSsWoRd')
122
+ # myapps = ProvisioningApi.new(gapp)
123
+ # list= myapps.retrieve_page_of_users("jsmtih")
124
+ # list.each{ |user| puts user.username}
125
+ def retrieve_page_of_users(start_username)
126
+ param='?startUsername='+start_username
127
+ response = @apps.request(:user_retrieve_all,param)
128
+ user_feed = Feed.new(response.elements["feed"], UserEntry)
129
+ end
130
+
131
+ # Updates an account in your domain, returns a UserEntry instance
132
+ # params :
133
+ # username is required and can't be updated.
134
+ # given_name and family_name are required, may be updated.
135
+ # if set to nil, every other parameter won't update the attribute.
136
+ # passwd_hash_function : string "SHA-1" or nil (default)
137
+ # admin : string "true" or string "false" or nil (no boolean : true or false).
138
+ # suspended : string "true" or string "false" or nil (no boolean : true or false)
139
+ # change_passwd : string "true" or string "false" or nil (no boolean : true or false)
140
+ # quota : limit en MB, ex : string "2048"
141
+ # ex :
142
+ # gapp = GApps.new('root@mydomain.com','PaSsWoRd')
143
+ # myapps = ProvisioningApi.new(gapp)
144
+ # user = myapps.update('jsmith', 'John', 'Smith', nil, nil, "true", nil, "true", nil)
145
+ # puts user.admin => "true"
146
+ def update_user(username, given_name, family_name, password=nil, passwd_hash_function=nil, admin=nil, suspended=nil, changepasswd=nil, quota=nil)
147
+ msg = ProvisioningMessage.new
148
+ msg.about_login(username,password,passwd_hash_function,admin,suspended, changepasswd)
149
+ msg.about_name(family_name, given_name)
150
+ msg.about_quota(quota) if quota
151
+ response = @apps.request(:user_update,username, msg.to_s)
152
+ #user_entry = UserEntry.new(response.elements["entry"])
153
+ end
154
+
155
+ # Deletes an account in your domain
156
+ # ex :
157
+ # gapp = GApps.new('root@mydomain.com','PaSsWoRd')
158
+ # myapps = ProvisioningApi.new(gapp)
159
+ # myapps.delete('jsmith')
160
+ def delete_user(username)
161
+ response = @apps.request(:user_delete,username)
162
+ end
163
+
164
+ # Creates a nickname for the username in your domain and returns a NicknameEntry instance
165
+ # gapp = GApps.new('root@mydomain.com','PaSsWoRd')
166
+ # myapps = ProvisioningApi.new(gapp)
167
+ # mynewnick = myapps.create_nickname('jsmith', 'john.smith')
168
+ def create_nickname(username, nickname)
169
+ msg = ProvisioningMessage.new
170
+ msg.about_login(username)
171
+ msg.about_nickname(nickname)
172
+ response = @apps.request(:nickname_create,nil, msg.to_s)
173
+ #nickname_entry = NicknameEntry.new(response.elements["entry"])
174
+ end
175
+
176
+ # Returns a NicknameEntry instance from a nickname
177
+ # ex :
178
+ # gapp = GApps.new('root@mydomain.com','PaSsWoRd')
179
+ # myapps = ProvisioningApi.new(gapp)
180
+ # nickname = myapps.retrieve_nickname('jsmith')
181
+ # puts "login : "+nickname.login
182
+ def retrieve_nickname(nickname)
183
+ xml_response = @apps.request(:nickname_retrieve, nickname)
184
+ nickname_entry = NicknameEntry.new(xml_response.elements["entry"])
185
+ end
186
+
187
+ # Returns a NicknameEntry array from a username
188
+ # ex : lists jsmith's nicknames
189
+ # gapp = GApps.new('root@mydomain.com','PaSsWoRd')
190
+ # myapps = ProvisioningApi.new(gapp)
191
+ # mynicks = myapps.retrieve('jsmith')
192
+ # mynicks.each {|nick| puts nick.nickname }
193
+ def retrieve_nicknames(username)
194
+ xml_response = @apps.request(:nickname_retrieve_all_for_user, username, @headers)
195
+
196
+ nicknames_feed = Feed.new(xml_response.elements["feed"], NicknameEntry)
197
+ nicknames_feed = add_next_feeds(nicknames_feed, xml_response, NicknameEntry)
198
+ end
199
+
200
+ # Returns a NicknameEntry array for the whole domain. May take a while depending on the number of users in your domain.
201
+ # gapp = GApps.new('root@mydomain.com','PaSsWoRd')
202
+ # myapps = ProvisioningApi.new(gapp)
203
+ # allnicks = myapps.retrieve_all_nicknames
204
+ # allnicks.each {|nick| puts nick.nickname }
205
+ def retrieve_all_nicknames
206
+ xml_response = @apps.request(:nickname_retrieve_all_in_domain, nil, @headers)
207
+ nicknames_feed = Feed.new(xml_response.elements["feed"], NicknameEntry)
208
+ nicknames_feed = add_next_feeds(nicknames_feed, xml_response, NicknameEntry)
209
+ end
210
+
211
+ # Deletes the nickname in your domain
212
+ # gapp = GApps.new('root@mydomain.com','PaSsWoRd')
213
+ # myapps = ProvisioningApi.new(gapp)
214
+ # myapps.delete_nickname('john.smith')
215
+ def delete_nickname(nickname)
216
+ response = @apps.request(:nickname_delete,nickname)
217
+ end
218
+
219
+ # Returns a NicknameEntry array populated with 100 nicknames, starting from a nickname
220
+ # ex :
221
+ # gapp = GApps.new('root@mydomain.com','PaSsWoRd')
222
+ # myapps = ProvisioningApi.new(gapp)
223
+ # list= myapps.retrieve_page_of_nicknames("joe")
224
+ # list.each{ |nick| puts nick.login}
225
+ def retrieve_page_of_nicknames(start_nickname)
226
+ param='?startNickname='+start_nickname
227
+ xml_response = @apps.request(:nickname_retrieve_all_in_domain, param, @headers)
228
+ nicknames_feed = Feed.new(xml_response.elements["feed"], NicknameEntry)
229
+ end
230
+
231
+ def create_group
232
+ raise NotImplementedError
233
+ end
234
+
235
+ def update_group
236
+ raise NotImplementedError
237
+ end
238
+
239
+ def retrieve_group
240
+ raise NotImplementedError
241
+ end
242
+
243
+ def delete_group
244
+ raise NotImplementedError
245
+ end
246
+
247
+ def add_member_to_group
248
+ raise NotImplementedError
249
+ end
250
+
251
+ def retrieve_members_of_group
252
+ raise NotImplementedError
253
+ end
254
+
255
+ def remove_member_from_group
256
+ raise NotImplementedError
257
+ end
258
+
259
+ def add_owner_to_group
260
+ raise NotImplementedError
261
+ end
262
+
263
+ def retrieve_owner_of_group
264
+ raise NotImplementedError
265
+ end
266
+
267
+ def remove_owner_from_group
268
+ raise NotImplementedError
269
+ end
270
+
271
+ # private methods
272
+ private #:nodoc:
273
+
274
+ # Associates methods, http verbs and URL for REST access
275
+ def setup_actions
276
+ domain = @apps.domain
277
+ path_user = '/a/feeds/'+domain+'/user/2.0'
278
+ path_nickname = '/a/feeds/'+domain+'/nickname/2.0'
279
+ path_email_list = '/a/feeds/'+domain+'/emailList/2.0'
280
+ path_group = '/a/feeds/group/2.0/'+domain
281
+
282
+ @apps.register_action(:domain_login, {:method => 'POST', :path => '/accounts/ClientLogin' })
283
+ @apps.register_action(:user_create, { :method => 'POST', :path => path_user })
284
+ @apps.register_action(:user_retrieve, { :method => 'GET', :path => path_user+'/' })
285
+ @apps.register_action(:user_retrieve_all, { :method => 'GET', :path => path_user })
286
+ @apps.register_action(:user_update, { :method => 'PUT', :path => path_user +'/' })
287
+ @apps.register_action(:user_delete, { :method => 'DELETE', :path => path_user +'/' })
288
+ @apps.register_action(:nickname_create, { :method => 'POST', :path =>path_nickname })
289
+ @apps.register_action(:nickname_retrieve, { :method => 'GET', :path =>path_nickname+'/' })
290
+ @apps.register_action(:nickname_retrieve_all_for_user, { :method => 'GET', :path =>path_nickname+'?username=' })
291
+ @apps.register_action(:nickname_retrieve_all_in_domain, { :method => 'GET', :path =>path_nickname })
292
+ @apps.register_action(:nickname_delete, { :method => 'DELETE', :path =>path_nickname+'/' })
293
+ @apps.register_action(:group_create, { :method => 'POST', :path => path_group })
294
+ @apps.register_action(:group_update, { :method => 'PUT', :path => path_group })
295
+ @apps.register_action(:group_retrieve, { :method => 'GET', :path => path_group })
296
+ @apps.register_action(:group_delete, { :method => 'DELETE', :path => path_group })
297
+
298
+ # special action "next" for linked feed results. :path will be affected with URL received in a link tag.
299
+ @apps.register_action(:next, {:method => 'GET', :path =>'' })
300
+ end
301
+
302
+ # Completes the feed by following et requesting the URL links
303
+ def add_next_feeds(current_feed, xml_content, element_class)
304
+ XPath.each(xml_content, 'feed/link') { |link|
305
+ if link.attributes.has_key?("rel") && link.attributes["rel"] == "next"
306
+ next_response = @apps.request(:next, link.attributes["href"])
307
+ current_feed.concat(Feed.new(next_response.elements["feed"], element_class))
308
+ current_feed = add_next_feeds(current_feed, next_response, element_class)
309
+ end
310
+ }
311
+ return current_feed
312
+ end
313
+ end
314
+
315
+
316
+ # UserEntry object.
317
+ #
318
+ # Handles API responses relative to a user
319
+ #
320
+ # Attributes :
321
+ # username : string
322
+ # given_name : string
323
+ # family_name : string
324
+ # suspended : string "true" or string "false"
325
+ # ip_whitelisted : string "true" or string "false"
326
+ # admin : string "true" or string "false"
327
+ # change_password_at_next_login : string "true" or string "false"
328
+ # agreed_to_terms : string "true" or string "false"
329
+ # quota_limit : string (value in MB)
330
+ class UserEntry
331
+ attr_reader :given_name, :family_name, :username, :suspended, :ip_whitelisted, :admin, :change_password_at_next_login, :agreed_to_terms, :quota_limit
332
+
333
+ # UserEntry constructor. Needs a REXML::Element <entry> as parameter
334
+ def initialize(entry) #:nodoc:
335
+ @family_name = entry.elements["apps:name"].attributes["familyName"]
336
+ @given_name = entry.elements["apps:name"].attributes["givenName"]
337
+ @username = entry.elements["apps:login"].attributes["userName"]
338
+ @suspended = entry.elements["apps:login"].attributes["suspended"]
339
+ @ip_whitelisted = entry.elements["apps:login"].attributes["ipWhitelisted"]
340
+ @admin = entry.elements["apps:login"].attributes["admin"]
341
+ @change_password_at_next_login = entry.elements["apps:login"].attributes["changePasswordAtNextLogin"]
342
+ @agreed_to_terms = entry.elements["apps:login"].attributes["agreedToTerms"]
343
+ @quota_limit = entry.elements["apps:quota"].attributes["limit"]
344
+ end
345
+
346
+ def to_s
347
+ outstr = "#<#{self.class}:0x#{self.object_id.to_s(16)}>\n"
348
+ instance_variables.sort.each do |v|
349
+ outstr += "\t#{v[1,v.length-1]} : #{instance_variable_get(v).to_s}\n"
350
+ end
351
+ outstr
352
+ end
353
+ end
354
+
355
+ # NicknameEntry object.
356
+ #
357
+ # Handles API responses relative to a nickname
358
+ #
359
+ # Attributes :
360
+ # login : string
361
+ # nickname : string
362
+ class NicknameEntry
363
+ attr_reader :login, :nickname
364
+
365
+ # NicknameEntry constructor. Needs a REXML::Element <entry> as parameter
366
+ def initialize(entry) #:nodoc:
367
+ @login = entry.elements["apps:login"].attributes["userName"]
368
+ if entry.elements["apps:nickname"].nil?
369
+ # IRJ Some call is failing 10 minutes into a run, I'll debug
370
+ @nickname = nil
371
+ else
372
+ @nickname = entry.elements["apps:nickname"].attributes["name"]
373
+ end
374
+ end
375
+
376
+ def to_s
377
+ outstr = "#<#{self.class}:0x#{self.object_id.to_s(16)}>\n"
378
+ outstr += "\t#{@login} : #{@nickname}"
379
+ end
380
+ end
381
+
382
+ # UserFeed object : Array populated with Element_class objects (UserEntry, NicknameEntry, EmailListEntry or EmailListRecipientEntry)
383
+ class Feed < Array #:nodoc:
384
+
385
+ # UserFeed constructor. Populates an array with Element_class objects. Each object is an xml <entry> parsed from the REXML::Element <feed>.
386
+ # Ex : user_feed = Feed.new(xml_feed, UserEntry)
387
+ # nickname_feed = Feed.new(xml_feed, NicknameEntry)
388
+ def initialize(xml_feed, element_class)
389
+ if xml_feed.respond_to? :elements
390
+ xml_feed.elements.each("entry"){ |entry| self << element_class.new(entry) }
391
+ end
392
+ end
393
+ end
394
+
395
+ class ProvisioningMessage < GData::RequestMessage #:nodoc:
396
+ def initialize
397
+ super
398
+ self.elements["atom:entry"].add_element "atom:category", {"scheme" => "http://schemas.google.com/g/2005#kind"}
399
+ end
400
+
401
+ # adds <apps:login> element in the message body.
402
+ # warning : if valued admin, suspended, or change_passwd_at_next_login must be the STRINGS "true" or "false", not the boolean true or false
403
+ # when needed to construct the message, should always been used before other "about_" methods so that the category tag can be overwritten
404
+ # only values permitted for hash_function_function_name : "SHA-1" or nil
405
+ def about_login(user_name, passwd=nil, hash_function_name=nil, admin=nil, suspended=nil, change_passwd_at_next_login=nil)
406
+ self.elements["atom:entry/atom:category"].add_attribute("term", "http://schemas.google.com/apps/2006#user")
407
+ self.elements["atom:entry"].add_element "apps:login", {"userName" => user_name }
408
+ self.elements["atom:entry/apps:login"].add_attribute("password", passwd) if not passwd.nil?
409
+ self.elements["atom:entry/apps:login"].add_attribute("hashFunctionName", hash_function_name) if not hash_function_name.nil?
410
+ self.elements["atom:entry/apps:login"].add_attribute("admin", admin) if not admin.nil?
411
+ self.elements["atom:entry/apps:login"].add_attribute("suspended", suspended) if not suspended.nil?
412
+ self.elements["atom:entry/apps:login"].add_attribute("changePasswordAtNextLogin", change_passwd_at_next_login) if not change_passwd_at_next_login.nil?
413
+ return self
414
+ end
415
+
416
+ # adds <apps:quota> in the message body.
417
+ # limit in MB: integer
418
+ def about_quota(limit)
419
+ self.elements["atom:entry"].add_element "apps:quota", {"limit" => limit }
420
+ return self
421
+ end
422
+
423
+ # adds <apps:name> in the message body.
424
+ def about_name(family_name, given_name)
425
+ self.elements["atom:entry"].add_element "apps:name", {"familyName" => family_name, "givenName" => given_name }
426
+ return self
427
+ end
428
+
429
+ # adds <apps:nickname> in the message body.
430
+ def about_nickname(name)
431
+ self.elements["atom:entry/atom:category"].add_attribute("term", "http://schemas.google.com/apps/2006#nickname")
432
+ self.elements["atom:entry"].add_element "apps:nickname", {"name" => name}
433
+ return self
434
+ end
435
+ end
436
+ end
437
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gdata2
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ version: "0.1"
9
+ platform: ruby
10
+ authors:
11
+ - "J\xC3\xA9r\xC3\xB4me Bousqui\xC3\xA9"
12
+ - Ivan R. Judson
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2009-02-20 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: hoe
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 1
30
+ - 8
31
+ - 3
32
+ version: 1.8.3
33
+ type: :development
34
+ version_requirements: *id001
35
+ description: gdata2 is a ruby wrapper for the google data apis
36
+ email: ivan.judson@montana.edu
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - History.txt
43
+ - Manifest.txt
44
+ - README.txt
45
+ files:
46
+ - CREDITS
47
+ - History.txt
48
+ - Manifest.txt
49
+ - README.txt
50
+ - Rakefile
51
+ - TODO
52
+ - gdata2.gemspec
53
+ - lib/gdata.rb
54
+ - lib/gdata/apps/provisioning.rb
55
+ has_rdoc: true
56
+ homepage: ""
57
+ licenses: []
58
+
59
+ post_install_message:
60
+ rdoc_options:
61
+ - --main
62
+ - README.txt
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ requirements: []
82
+
83
+ rubyforge_project: gdata2
84
+ rubygems_version: 1.3.7
85
+ signing_key:
86
+ specification_version: 2
87
+ summary: Ruby wrapper for Google Data API's
88
+ test_files: []
89
+