google_apps_api 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +17 -0
- data/Rakefile +56 -0
- data/VERSION +1 -0
- data/google_apps_api.gemspec +85 -0
- data/lib/config/calendar.yml +34 -0
- data/lib/config/provisioning.yml +36 -0
- data/lib/google_apps_api/base_api.rb +157 -0
- data/lib/google_apps_api/calendar.rb +65 -0
- data/lib/google_apps_api/calendar_resources.rb +34 -0
- data/lib/google_apps_api/contacts.rb +53 -0
- data/lib/google_apps_api/exceptions.rb +19 -0
- data/lib/google_apps_api/provisioning.rb +294 -0
- data/lib/google_apps_api/user_profiles.rb +101 -0
- data/lib/google_apps_api.rb +15 -0
- data/lib/load_config.rb +17 -0
- data/private/gapps-config.yml +5 -0
- data/private/userscalendars.xml +113 -0
- data/test/google_apps_api-calendar_resources_test.rb +41 -0
- data/test/google_apps_api_calendar_test.rb +81 -0
- data/test/google_apps_api_contacts_test.rb +27 -0
- data/test/google_apps_api_provisioning_test.rb +78 -0
- data/test/google_apps_api_user_profiles_test.rb +30 -0
- data/test/helper.rb +10 -0
- data/test/test_helper.rb +15 -0
- metadata +127 -0
@@ -0,0 +1,294 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
module GoogleAppsApi #:nodoc:
|
4
|
+
module Provisioning
|
5
|
+
class Api < GoogleAppsApi::BaseApi
|
6
|
+
attr_reader :token
|
7
|
+
|
8
|
+
|
9
|
+
def initialize(*args)
|
10
|
+
super(:provisioning, *args)
|
11
|
+
end
|
12
|
+
|
13
|
+
def retrieve_user(username)
|
14
|
+
request(:retrieve_user, :username => username)
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def retrieve_all_users
|
19
|
+
request(:retrieve_all_users)
|
20
|
+
end
|
21
|
+
#
|
22
|
+
# # Returns a UserEntry array populated with 100 users, starting from a username
|
23
|
+
# # ex :
|
24
|
+
# # myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
25
|
+
# # list= myapps.retrieve_page_of_users("jsmtih")
|
26
|
+
# # list.each{ |user| puts user.username}
|
27
|
+
# def retrieve_page_of_users(start_username)
|
28
|
+
# param='?startUsername='+start_username
|
29
|
+
# response = request(:user_retrieve_all,param,@headers)
|
30
|
+
# user_feed = Feed.new(response.elements["feed"], UserEntry)
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
#
|
34
|
+
# def contacts_retrieve_all()
|
35
|
+
# response = request(:contacts_retrieve_all,nil, @headers)
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# Creates an account in your domain, returns a UserEntry instance
|
39
|
+
# params :
|
40
|
+
# username, given_name, family_name and password are required
|
41
|
+
# passwd_hash_function (optional) : nil (default) or "SHA-1"
|
42
|
+
# quota (optional) : nil (default) or integer for limit in MB
|
43
|
+
# ex :
|
44
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
45
|
+
# user = myapps.create('jsmith', 'John', 'Smith', 'p455wD')
|
46
|
+
#
|
47
|
+
# 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.
|
48
|
+
def create_user(username, *args)
|
49
|
+
options = args.extract_options!
|
50
|
+
options.each { |k,v| options[k] = escapeXML(v)}
|
51
|
+
|
52
|
+
res = <<-DESCXML
|
53
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
54
|
+
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom"
|
55
|
+
xmlns:apps="http://schemas.google.com/apps/2006">
|
56
|
+
<atom:category scheme="http://schemas.google.com/g/2005#kind"
|
57
|
+
term="http://schemas.google.com/apps/2006#user"/>
|
58
|
+
<apps:login userName="#{escapeXML(username)}"
|
59
|
+
password="#{options[:password]}" suspended="false"/>
|
60
|
+
<apps:name familyName="#{options[:family_name]}" givenName="#{options[:given_name]}"/>
|
61
|
+
</atom:entry>
|
62
|
+
|
63
|
+
DESCXML
|
64
|
+
|
65
|
+
|
66
|
+
request(:create_user, :body => res.strip)
|
67
|
+
end
|
68
|
+
#
|
69
|
+
# # Updates an account in your domain, returns a UserEntry instance
|
70
|
+
# # params :
|
71
|
+
# # username is required and can't be updated.
|
72
|
+
# # given_name and family_name are required, may be updated.
|
73
|
+
# # if set to nil, every other parameter won't update the attribute.
|
74
|
+
# # passwd_hash_function : string "SHA-1", "MD5" or nil (default)
|
75
|
+
# # admin : string "true" or string "false" or nil (no boolean : true or false).
|
76
|
+
# # suspended : string "true" or string "false" or nil (no boolean : true or false)
|
77
|
+
# # change_passwd : string "true" or string "false" or nil (no boolean : true or false)
|
78
|
+
# # quota : limit en MB, ex : string "2048"
|
79
|
+
# # ex :
|
80
|
+
# # myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
81
|
+
# # user = myapps.update('jsmith', 'John', 'Smith', nil, nil, "true", nil, "true", nil)
|
82
|
+
# # puts user.admin => "true"
|
83
|
+
def update_user(username, *args)
|
84
|
+
options = args.extract_options!
|
85
|
+
options.each { |k,v| options[k] = escapeXML(v)}
|
86
|
+
|
87
|
+
res = <<-DESCXML
|
88
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
89
|
+
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom"
|
90
|
+
xmlns:apps="http://schemas.google.com/apps/2006">
|
91
|
+
<atom:category scheme="http://schemas.google.com/g/2005#kind"
|
92
|
+
term="http://schemas.google.com/apps/2006#user"/>
|
93
|
+
<apps:name familyName="#{options[:family_name]}" givenName="#{options[:given_name]}"/>
|
94
|
+
</atom:entry>
|
95
|
+
|
96
|
+
DESCXML
|
97
|
+
request(:update_user, :username => username, :body => res.strip)
|
98
|
+
end
|
99
|
+
#
|
100
|
+
# # Renames a user, returns a UserEntry instance
|
101
|
+
# # ex :
|
102
|
+
# #
|
103
|
+
# # myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
104
|
+
# # user = myapps.rename_user('jsmith','jdoe')
|
105
|
+
# #
|
106
|
+
# # It is recommended to log out rhe user from all browser sessions and service before renaming.
|
107
|
+
# # Once renamed, the old username becomes a nickname of the new username.
|
108
|
+
# # Note from Google: Google Talk will lose all remembered chat invitations after renaming.
|
109
|
+
# # The user must request permission to chat with friends again.
|
110
|
+
# # Also, when a user is renamed, the old username is retained as a nickname to ensure continuous mail delivery in the case of email forwarding settings.
|
111
|
+
# # To remove the nickname, you should issue an HTTP DELETE to the nicknames feed after renaming.
|
112
|
+
# def rename_user(username, new_username)
|
113
|
+
# msg = RequestMessage.new
|
114
|
+
# msg.about_login(new_username)
|
115
|
+
# msg.add_path('https://'+@@google_host+@action[:user_rename][:path]+username)
|
116
|
+
# response = request(:user_update,username,@headers, msg.to_s)
|
117
|
+
# end
|
118
|
+
#
|
119
|
+
# # Suspends an account in your domain, returns a UserEntry instance
|
120
|
+
# # ex :
|
121
|
+
# # myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
122
|
+
# # user = myapps.suspend('jsmith')
|
123
|
+
# # puts user.suspended => "true"
|
124
|
+
# def suspend_user(username)
|
125
|
+
# msg = RequestMessage.new
|
126
|
+
# msg.about_login(username,nil,nil,nil,"true")
|
127
|
+
# msg.add_path('https://'+@@google_host+@action[:user_update][:path]+username)
|
128
|
+
# response = request(:user_update,username,@headers, msg.to_s)
|
129
|
+
# user_entry = UserEntry.new(response.elements["entry"])
|
130
|
+
# end
|
131
|
+
#
|
132
|
+
# # Restores a suspended account in your domain, returns a UserEntry instance
|
133
|
+
# # ex :
|
134
|
+
# # myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
135
|
+
# # user = myapps.restore('jsmith')
|
136
|
+
# # puts user.suspended => "false"
|
137
|
+
# def restore_user(username)
|
138
|
+
# msg = RequestMessage.new
|
139
|
+
# msg.about_login(username,nil,nil,nil,"false")
|
140
|
+
# msg.add_path('https://'+@@google_host+@action[:user_update][:path]+username)
|
141
|
+
# response = request(:user_update,username,@headers, msg.to_s)
|
142
|
+
# user_entry = UserEntry.new(response.elements["entry"])
|
143
|
+
# end
|
144
|
+
#
|
145
|
+
# # Deletes an account in your domain
|
146
|
+
# # ex :
|
147
|
+
# # myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
148
|
+
# # myapps.delete('jsmith')
|
149
|
+
def delete_user(username)
|
150
|
+
response = request(:delete_user, :username => username)
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
#
|
158
|
+
#
|
159
|
+
# class RequestMessage < Document #:nodoc:
|
160
|
+
# # Request message constructor.
|
161
|
+
# # parameter type : "user", "nickname" or "emailList"
|
162
|
+
#
|
163
|
+
# # creates the object and initiates the construction
|
164
|
+
# def initialize
|
165
|
+
# super '<?xml version="1.0" encoding="UTF-8"?>'
|
166
|
+
# self.add_element "atom:entry", {"xmlns:apps" => "http://schemas.google.com/apps/2006",
|
167
|
+
# "xmlns:gd" => "http://schemas.google.com/g/2005",
|
168
|
+
# "xmlns:atom" => "http://www.w3.org/2005/Atom"}
|
169
|
+
#
|
170
|
+
# self.elements["atom:entry"].add_element "atom:category", {"scheme" => "http://schemas.google.com/g/2005#kind"}
|
171
|
+
#
|
172
|
+
# end
|
173
|
+
#
|
174
|
+
# # adds <atom:id> element in the message body. Url is inserted as a text.
|
175
|
+
# def add_path(url)
|
176
|
+
# self.elements["atom:entry"].add_element "atom:id"
|
177
|
+
# self.elements["atom:entry/atom:id"].text = url
|
178
|
+
# end
|
179
|
+
#
|
180
|
+
# # adds <apps:emailList> element in the message body.
|
181
|
+
# def about_email_list(email_list)
|
182
|
+
# self.elements["atom:entry/atom:category"].add_attribute("term", "http://schemas.google.com/apps/2006#emailList")
|
183
|
+
# self.elements["atom:entry"].add_element "apps:emailList", {"name" => email_list }
|
184
|
+
# end
|
185
|
+
#
|
186
|
+
# # adds <apps:property> element in the message body for a group.
|
187
|
+
# def about_group(group_id, properties)
|
188
|
+
# self.elements["atom:entry/atom:category"].add_attribute("term", "http://schemas.google.com/apps/2006#emailList")
|
189
|
+
# self.elements["atom:entry"].add_element "apps:property", {"name" => "groupId", "value" => group_id }
|
190
|
+
# self.elements["atom:entry"].add_element "apps:property", {"name" => "groupName", "value" => properties[0] }
|
191
|
+
# self.elements["atom:entry"].add_element "apps:property", {"name" => "description", "value" => properties[1] }
|
192
|
+
# self.elements["atom:entry"].add_element "apps:property", {"name" => "emailPermission", "value" => properties[2] }
|
193
|
+
# end
|
194
|
+
#
|
195
|
+
# # adds <apps:property> element in the message body for a member.
|
196
|
+
# def about_member(email_address)
|
197
|
+
# self.elements["atom:entry/atom:category"].add_attribute("term", "http://schemas.google.com/apps/2006#user")
|
198
|
+
# self.elements["atom:entry"].add_element "apps:property", {"name" => "memberId", "value" => email_address }
|
199
|
+
# end
|
200
|
+
#
|
201
|
+
# # adds <apps:property> element in the message body for an owner.
|
202
|
+
# def about_owner(email_address)
|
203
|
+
# self.elements["atom:entry/atom:category"].add_attribute("term", "http://schemas.google.com/apps/2006#user")
|
204
|
+
# self.elements["atom:entry"].add_element "apps:property", {"name" => "email", "value" => email_address }
|
205
|
+
# end
|
206
|
+
#
|
207
|
+
#
|
208
|
+
# # adds <apps:login> element in the message body.
|
209
|
+
# # warning : if valued admin, suspended, or change_passwd_at_next_login must be the STRINGS "true" or "false", not the boolean true or false
|
210
|
+
# # when needed to construct the message, should always been used before other "about_" methods so that the category tag can be overwritten
|
211
|
+
# # only values permitted for hash_function_function_name : "SHA-1", "MD5" or nil
|
212
|
+
# def about_login(user_name, passwd=nil, hash_function_name=nil, admin=nil, suspended=nil, change_passwd_at_next_login=nil)
|
213
|
+
# self.elements["atom:entry/atom:category"].add_attribute("term", "http://schemas.google.com/apps/2006#user")
|
214
|
+
# self.elements["atom:entry"].add_element "apps:login", {"userName" => user_name }
|
215
|
+
# self.elements["atom:entry/apps:login"].add_attribute("password", passwd) if not passwd.nil?
|
216
|
+
# self.elements["atom:entry/apps:login"].add_attribute("hashFunctionName", hash_function_name) if not hash_function_name.nil?
|
217
|
+
# self.elements["atom:entry/apps:login"].add_attribute("admin", admin) if not admin.nil?
|
218
|
+
# self.elements["atom:entry/apps:login"].add_attribute("suspended", suspended) if not suspended.nil?
|
219
|
+
# self.elements["atom:entry/apps:login"].add_attribute("changePasswordAtNextLogin", change_passwd_at_next_login) if not change_passwd_at_next_login.nil?
|
220
|
+
# return self
|
221
|
+
# end
|
222
|
+
#
|
223
|
+
# # adds <apps:quota> in the message body.
|
224
|
+
# # limit in MB: integer
|
225
|
+
# def about_quota(limit)
|
226
|
+
# self.elements["atom:entry"].add_element "apps:quota", {"limit" => limit }
|
227
|
+
# return self
|
228
|
+
# end
|
229
|
+
#
|
230
|
+
# # adds <apps:name> in the message body.
|
231
|
+
# def about_name(family_name, given_name)
|
232
|
+
# self.elements["atom:entry"].add_element "apps:name", {"familyName" => family_name, "givenName" => given_name }
|
233
|
+
# return self
|
234
|
+
# end
|
235
|
+
#
|
236
|
+
# # adds <apps:nickname> in the message body.
|
237
|
+
# def about_nickname(name)
|
238
|
+
# self.elements["atom:entry/atom:category"].add_attribute("term", "http://schemas.google.com/apps/2006#nickname")
|
239
|
+
# self.elements["atom:entry"].add_element "apps:nickname", {"name" => name}
|
240
|
+
# return self
|
241
|
+
# end
|
242
|
+
#
|
243
|
+
# # adds <gd:who> in the message body.
|
244
|
+
# def about_who(email)
|
245
|
+
# self.elements["atom:entry"].add_element "gd:who", {"email" => email }
|
246
|
+
# return self
|
247
|
+
# end
|
248
|
+
#
|
249
|
+
# end
|
250
|
+
# end
|
251
|
+
end
|
252
|
+
|
253
|
+
|
254
|
+
|
255
|
+
class UserEntry < Entry
|
256
|
+
attr_accessor :given_name, :family_name, :username, :suspended, :ip_whitelisted, :admin, :change_password_at_next_login, :agreed_to_terms, :quota_limit
|
257
|
+
|
258
|
+
def initialize(xml = nil)
|
259
|
+
if xml
|
260
|
+
@family_name = xml.at_xpath("//apps:name").attribute("familyName").content
|
261
|
+
@given_name = xml.at_xpath("//apps:name").attribute("givenName").content
|
262
|
+
@username = xml.at_xpath("//apps:login").attribute("userName").content
|
263
|
+
@suspended = xml.at_xpath("//apps:login").attribute("suspended").content
|
264
|
+
@ip_whitelisted = xml.at_xpath("//apps:login").attribute("ipWhitelisted").content
|
265
|
+
@admin = xml.at_xpath("//apps:login").attribute("admin").content
|
266
|
+
@change_password_at_next_login = xml.at_xpath("//apps:login").attribute("changePasswordAtNextLogin").content
|
267
|
+
@agreed_to_terms = xml.at_xpath("//apps:login").attribute("agreedToTerms").content
|
268
|
+
@quota_limit = xml.at_xpath("//apps:quota").attribute("limit").content
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
def to_s
|
273
|
+
username
|
274
|
+
end
|
275
|
+
|
276
|
+
def inspect
|
277
|
+
"<UserEntry: #{username} : #{given_name} #{family_name}>"
|
278
|
+
end
|
279
|
+
|
280
|
+
def create_message(*args)
|
281
|
+
|
282
|
+
end
|
283
|
+
#
|
284
|
+
# def add_message
|
285
|
+
# Nokogiri::XML::Builder.new { |xml|
|
286
|
+
# xml.entry(:xmlns => "http://www.w3.org/2005/Atom") {
|
287
|
+
# xml.id_ {
|
288
|
+
# xml.text id.to_s
|
289
|
+
# }
|
290
|
+
# }
|
291
|
+
# }.to_xml
|
292
|
+
# end
|
293
|
+
end
|
294
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
# require 'cgi'
|
4
|
+
# require 'rexml/document'
|
5
|
+
#
|
6
|
+
|
7
|
+
include REXML
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
module GoogleAppsApi #:nodoc:
|
12
|
+
module UserProfiles
|
13
|
+
|
14
|
+
|
15
|
+
class Api < GoogleAppsApi::BaseApi
|
16
|
+
|
17
|
+
attr_reader :token
|
18
|
+
|
19
|
+
def initialize(*args)
|
20
|
+
action_list = {
|
21
|
+
:domain_login => [:post, ':auth:/accounts/ClientLogin' ],
|
22
|
+
:retrieve_all => [:get, ':basic_path:/full?v=3.0'],
|
23
|
+
:retrieve_user => [:get, ':basic_path:/full/'],
|
24
|
+
:set_emails => [:put, ':basic_path:/full/'],
|
25
|
+
:next => [:get, '' ]
|
26
|
+
}
|
27
|
+
|
28
|
+
options = args.extract_options!
|
29
|
+
domain = options[:domain]
|
30
|
+
|
31
|
+
options.merge!(:action_hash => action_list, :auth => "https://www.google.com", :feed => "https://www.google.com", :service => "cp")
|
32
|
+
options[:basic_path] = options[:feed] + "/m8/feeds/profiles/domain/#{options[:domain]}"
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
super(options)
|
37
|
+
end
|
38
|
+
|
39
|
+
def retrieve_all()
|
40
|
+
response = request(:retrieve_all)
|
41
|
+
return response.to_s
|
42
|
+
end
|
43
|
+
|
44
|
+
def retrieve_user(user)
|
45
|
+
response = request(:retrieve_user, :query => user + "?v=3.0")
|
46
|
+
return response.to_s
|
47
|
+
end
|
48
|
+
|
49
|
+
def set_emails(user, *args)
|
50
|
+
emails = args.extract_options!
|
51
|
+
doc = Document.new(retrieve_user(user).to_s)
|
52
|
+
doc.elements.each("entry/gd:email") do |e|
|
53
|
+
|
54
|
+
e.parent.delete(e)
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
primary = emails.delete(:primary) || :other
|
59
|
+
|
60
|
+
base = doc.elements["entry"]
|
61
|
+
emails.each_pair do |loc, email|
|
62
|
+
base.add_element("gd:email", "address" => email, "rel" => "http://schemas.google.com/g/2005##{loc.to_s}", "primary" => loc == primary ? "true" : "false")
|
63
|
+
end
|
64
|
+
|
65
|
+
response = request(:set_emails,:query => user + "?v=3.0", :body => doc.to_s)
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
# class RequestMessage < Document #:nodoc:
|
71
|
+
# # Request message constructor.
|
72
|
+
# # parameter type : "user", "nickname" or "emailList"
|
73
|
+
#
|
74
|
+
# # creates the object and initiates the construction
|
75
|
+
# def initialize(*args)
|
76
|
+
# options = args.extract_options!
|
77
|
+
# super '<?xml version="1.0" encoding="UTF-8"?>'
|
78
|
+
# self.add_element "entry", { "xmlns:gd" => "http://schemas.google.com/g/2005",
|
79
|
+
# "xmlns:atom" => "http://www.w3.org/2005/Atom", "xmlns:batch" => 'http://schemas.google.com/gdata/batch', "xmlns:gContact" => "http://schemas.google.com/contact/2008"}
|
80
|
+
# # self.elements["entry"].add_element "atom:category", {"scheme" => "http://schemas.google.com/g/2005#kind", "term" => "http://schemas.google.com/contact/2008#contact"}
|
81
|
+
# end
|
82
|
+
#
|
83
|
+
# def add_contact(*args)
|
84
|
+
# options = args.extract_options!
|
85
|
+
# base = self.elements["atom:entry"]
|
86
|
+
# base.add_element("atom:title", {"type" => "text"}).text = options[:name]
|
87
|
+
# base.add_element("atom:content", {"type" => "text"}).text = "Notes"
|
88
|
+
# (options[:email] || {}).each_pair do |email_type, address|
|
89
|
+
# base.add_element("gd:email", {"rel" => "http://schemas.google.com/g/2005##{email_type.to_s}", "address" => address})
|
90
|
+
# end
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# def update_contact(*args)
|
94
|
+
# options = args.extract_options!
|
95
|
+
# end
|
96
|
+
# end
|
97
|
+
#
|
98
|
+
# end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'httpclient'
|
2
|
+
require 'cgi'
|
3
|
+
require 'nokogiri'
|
4
|
+
require "active_support"
|
5
|
+
|
6
|
+
require "load_config"
|
7
|
+
require "google_apps_api/base_api"
|
8
|
+
require "google_apps_api/calendar"
|
9
|
+
require "google_apps_api/calendar_resources"
|
10
|
+
require "google_apps_api/provisioning"
|
11
|
+
require "google_apps_api/exceptions"
|
12
|
+
require "google_apps_api/contacts"
|
13
|
+
require "google_apps_api/user_profiles"
|
14
|
+
|
15
|
+
|
data/lib/load_config.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module GoogleAppsApi
|
2
|
+
|
3
|
+
def self.load_yaml_configs
|
4
|
+
result = {}
|
5
|
+
Dir.glob(File.dirname(__FILE__) + "/config/*.yml").each do |file|
|
6
|
+
result.merge!(YAML::load(File.open(file)))
|
7
|
+
end
|
8
|
+
|
9
|
+
return result
|
10
|
+
end
|
11
|
+
|
12
|
+
@@config = GoogleAppsApi::load_yaml_configs
|
13
|
+
|
14
|
+
mattr_reader :config
|
15
|
+
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app" xmlns:gCal="http://schemas.google.com/gCal/2005" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:gd="http://schemas.google.com/g/2005" gd:etag="W/"CUcERH0_fyp7IWA9WxFRGUw."" gd:kind="calendar#calendarFeed">
|
3
|
+
<id>http://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/allcalendars/full</id>
|
4
|
+
<updated>2010-05-03T18:56:45.347Z</updated>
|
5
|
+
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/gCal/2005#calendarmeta"/>
|
6
|
+
<title>jws2135@ocelot.cul.columbia.edu's Calendar List</title>
|
7
|
+
<link rel="alternate" type="text/html" href="http://www.google.com/calendar/render"/>
|
8
|
+
<link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="https://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/allcalendars/full"/>
|
9
|
+
<link rel="http://schemas.google.com/g/2005#post" type="application/atom+xml" href="https://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/allcalendars/full"/>
|
10
|
+
<link rel="self" type="application/atom+xml" href="https://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/allcalendars/full"/>
|
11
|
+
<author>
|
12
|
+
<name>jws2135@ocelot.cul.columbia.edu</name>
|
13
|
+
<email>jws2135@ocelot.cul.columbia.edu</email>
|
14
|
+
</author>
|
15
|
+
<generator version="1.0" uri="http://www.google.com/calendar">Google Calendar</generator>
|
16
|
+
<openSearch:startIndex>1</openSearch:startIndex>
|
17
|
+
<entry gd:etag="W/"A0AFR347eCp7IWA9WxFRF0U."" gd:kind="calendar#calendar">
|
18
|
+
<id>http://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/calendars/jws2135%40ocelot.cul.columbia.edu</id>
|
19
|
+
<published>2010-05-03T18:56:45.279Z</published>
|
20
|
+
<updated>2010-05-02T08:41:56.000Z</updated>
|
21
|
+
<app:edited>2010-05-02T08:41:56.000Z</app:edited>
|
22
|
+
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/gCal/2005#calendarmeta"/>
|
23
|
+
<title type="text">jws2135@ocelot.cul.columbia.edu</title>
|
24
|
+
<content type="application/atom+xml" src="http://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/private/full"/>
|
25
|
+
<link rel="alternate" type="application/atom+xml" href="http://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/private/full"/>
|
26
|
+
<link rel="http://schemas.google.com/gCal/2005#eventFeed" type="application/atom+xml" href="http://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/private/full"/>
|
27
|
+
<link rel="http://schemas.google.com/acl/2007#accessControlList" type="application/atom+xml" href="http://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/acl/full"/>
|
28
|
+
<link rel="self" type="application/atom+xml" href="https://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/allcalendars/full/jws2135%40ocelot.cul.columbia.edu"/>
|
29
|
+
<link rel="edit" type="application/atom+xml" href="https://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/allcalendars/full/jws2135%40ocelot.cul.columbia.edu"/>
|
30
|
+
<author>
|
31
|
+
<name>jws2135@ocelot.cul.columbia.edu</name>
|
32
|
+
<email>jws2135@ocelot.cul.columbia.edu</email>
|
33
|
+
</author>
|
34
|
+
<gCal:accesslevel value="owner"/>
|
35
|
+
<gCal:color value="#A32929"/>
|
36
|
+
<gCal:hidden value="false"/>
|
37
|
+
<gCal:selected value="true"/>
|
38
|
+
<gCal:timezone value="America/New_York"/>
|
39
|
+
<gCal:timesCleaned value="0"/>
|
40
|
+
</entry>
|
41
|
+
<entry gd:etag="W/"D0QFQX47eCp7IWA9WxFSFks."" gd:kind="calendar#calendar">
|
42
|
+
<id>http://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/calendars/ocelot.cul.columbia.edu_i1upo9o0jh38ot1js88paksntk%40group.calendar.google.com</id>
|
43
|
+
<published>2010-05-03T18:56:45.337Z</published>
|
44
|
+
<updated>2010-04-19T08:21:50.000Z</updated>
|
45
|
+
<app:edited>2010-04-19T08:21:50.000Z</app:edited>
|
46
|
+
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/gCal/2005#calendarmeta"/>
|
47
|
+
<title type="text">James' Private</title>
|
48
|
+
<summary type="text"/>
|
49
|
+
<content type="application/atom+xml" src="http://www.google.com/calendar/feeds/ocelot.cul.columbia.edu_i1upo9o0jh38ot1js88paksntk%40group.calendar.google.com/private/full"/>
|
50
|
+
<link rel="alternate" type="application/atom+xml" href="http://www.google.com/calendar/feeds/ocelot.cul.columbia.edu_i1upo9o0jh38ot1js88paksntk%40group.calendar.google.com/private/full"/>
|
51
|
+
<link rel="http://schemas.google.com/gCal/2005#eventFeed" type="application/atom+xml" href="http://www.google.com/calendar/feeds/ocelot.cul.columbia.edu_i1upo9o0jh38ot1js88paksntk%40group.calendar.google.com/private/full"/>
|
52
|
+
<link rel="http://schemas.google.com/acl/2007#accessControlList" type="application/atom+xml" href="http://www.google.com/calendar/feeds/ocelot.cul.columbia.edu_i1upo9o0jh38ot1js88paksntk%40group.calendar.google.com/acl/full"/>
|
53
|
+
<link rel="self" type="application/atom+xml" href="https://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/allcalendars/full/ocelot.cul.columbia.edu_i1upo9o0jh38ot1js88paksntk%40group.calendar.google.com"/>
|
54
|
+
<link rel="edit" type="application/atom+xml" href="https://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/allcalendars/full/ocelot.cul.columbia.edu_i1upo9o0jh38ot1js88paksntk%40group.calendar.google.com"/>
|
55
|
+
<author>
|
56
|
+
<name>James' Private</name>
|
57
|
+
</author>
|
58
|
+
<gCal:accesslevel value="owner"/>
|
59
|
+
<gCal:color value="#0D7813"/>
|
60
|
+
<gCal:hidden value="false"/>
|
61
|
+
<gd:where valueString=""/>
|
62
|
+
<gCal:selected value="true"/>
|
63
|
+
<gCal:timezone value="UTC"/>
|
64
|
+
<gCal:timesCleaned value="0"/>
|
65
|
+
</entry>
|
66
|
+
<entry gd:etag="W/"CkAMQn47eCp7IWA9WxFSEk4."" gd:kind="calendar#calendar">
|
67
|
+
<id>http://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/calendars/nco2104%40ocelot.cul.columbia.edu</id>
|
68
|
+
<published>2010-05-03T18:56:45.326Z</published>
|
69
|
+
<updated>2010-04-14T07:39:43.000Z</updated>
|
70
|
+
<app:edited>2010-04-14T07:39:43.000Z</app:edited>
|
71
|
+
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/gCal/2005#calendarmeta"/>
|
72
|
+
<title type="text">nco2104@ocelot.cul.columbia.edu</title>
|
73
|
+
<content type="application/atom+xml" src="http://www.google.com/calendar/feeds/nco2104%40ocelot.cul.columbia.edu/private/full"/>
|
74
|
+
<link rel="alternate" type="application/atom+xml" href="http://www.google.com/calendar/feeds/nco2104%40ocelot.cul.columbia.edu/private/full"/>
|
75
|
+
<link rel="http://schemas.google.com/gCal/2005#eventFeed" type="application/atom+xml" href="http://www.google.com/calendar/feeds/nco2104%40ocelot.cul.columbia.edu/private/full"/>
|
76
|
+
<link rel="http://schemas.google.com/acl/2007#accessControlList" type="application/atom+xml" href="http://www.google.com/calendar/feeds/nco2104%40ocelot.cul.columbia.edu/acl/full"/>
|
77
|
+
<link rel="self" type="application/atom+xml" href="https://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/allcalendars/full/nco2104%40ocelot.cul.columbia.edu"/>
|
78
|
+
<link rel="edit" type="application/atom+xml" href="https://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/allcalendars/full/nco2104%40ocelot.cul.columbia.edu"/>
|
79
|
+
<author>
|
80
|
+
<name>nco2104@ocelot.cul.columbia.edu</name>
|
81
|
+
<email>nco2104@ocelot.cul.columbia.edu</email>
|
82
|
+
</author>
|
83
|
+
<gCal:accesslevel value="root"/>
|
84
|
+
<gCal:color value="#AB8B00"/>
|
85
|
+
<gCal:hidden value="false"/>
|
86
|
+
<gCal:selected value="true"/>
|
87
|
+
<gCal:timezone value="America/New_York"/>
|
88
|
+
<gCal:timesCleaned value="0"/>
|
89
|
+
</entry>
|
90
|
+
<entry gd:etag="W/"DkYHR347eCp7IWA9WxFRGEU."" gd:kind="calendar#calendar">
|
91
|
+
<id>http://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/calendars/en.usa%23holiday%40group.v.calendar.google.com</id>
|
92
|
+
<published>2010-05-03T18:56:45.279Z</published>
|
93
|
+
<updated>2010-05-03T10:55:36.000Z</updated>
|
94
|
+
<app:edited>2010-05-03T10:55:36.000Z</app:edited>
|
95
|
+
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/gCal/2005#calendarmeta"/>
|
96
|
+
<title type="text">US Holidays</title>
|
97
|
+
<summary type="text">US Holidays</summary>
|
98
|
+
<content type="application/atom+xml" src="http://www.google.com/calendar/feeds/en.usa%23holiday%40group.v.calendar.google.com/private/full"/>
|
99
|
+
<link rel="alternate" type="application/atom+xml" href="http://www.google.com/calendar/feeds/en.usa%23holiday%40group.v.calendar.google.com/private/full"/>
|
100
|
+
<link rel="http://schemas.google.com/gCal/2005#eventFeed" type="application/atom+xml" href="http://www.google.com/calendar/feeds/en.usa%23holiday%40group.v.calendar.google.com/private/full"/>
|
101
|
+
<link rel="self" type="application/atom+xml" href="https://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/allcalendars/full/en.usa%23holiday%40group.v.calendar.google.com"/>
|
102
|
+
<link rel="edit" type="application/atom+xml" href="https://www.google.com/calendar/feeds/jws2135%40ocelot.cul.columbia.edu/allcalendars/full/en.usa%23holiday%40group.v.calendar.google.com"/>
|
103
|
+
<author>
|
104
|
+
<name>US Holidays</name>
|
105
|
+
</author>
|
106
|
+
<gCal:accesslevel value="read"/>
|
107
|
+
<gCal:color value="#2952A3"/>
|
108
|
+
<gCal:hidden value="false"/>
|
109
|
+
<gCal:selected value="true"/>
|
110
|
+
<gCal:timezone value="America/New_York"/>
|
111
|
+
<gCal:timesCleaned value="0"/>
|
112
|
+
</entry>
|
113
|
+
</feed>
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# require 'test_helper'
|
2
|
+
#
|
3
|
+
# class GappsCalendarResourcesTest < Test::Unit::TestCase
|
4
|
+
#
|
5
|
+
# context "given a connection to apps.cul" do
|
6
|
+
# setup do
|
7
|
+
# gapps_config =YAML::load_file("private/gapps-config.yml")["apps_ocelot"].symbolize_keys!
|
8
|
+
# @api = GoogleAppsApi::CalendarResources::Api.new(gapps_config)
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# should "have a token" do
|
12
|
+
# assert @api.token
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
#
|
16
|
+
#
|
17
|
+
# should "be able to retrieve all resources" do
|
18
|
+
# assert @api.retrieve_all_resources
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# #
|
22
|
+
# # should "be able to create a user" do
|
23
|
+
# # assert_raises GoogleAppsApi::GDataError do
|
24
|
+
# # @api.retrieve_user("not_a_real_user")
|
25
|
+
# # end
|
26
|
+
# #
|
27
|
+
# # @api.create_user("not_a_real_user", "Not", "Real", "test_password", nil)
|
28
|
+
# #
|
29
|
+
# # assert_equal @api.retrieve_user("not_a_real_user").username, "not_a_real_user"
|
30
|
+
# #
|
31
|
+
# # @api.delete_user("not_a_real_user")
|
32
|
+
# #
|
33
|
+
# # assert_raises GoogleAppsApi::GDataError do
|
34
|
+
# # @api.retrieve_user("not_a_real_user")
|
35
|
+
# # end
|
36
|
+
#
|
37
|
+
#
|
38
|
+
#
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# end
|