google_apps_api 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+
@@ -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,5 @@
1
+ apps_ocelot:
2
+ domain: ocelot.cul.columbia.edu
3
+ admin_user: _sc_api
4
+ admin_password: G6Jb1sYEbYVwye
5
+ admin_email: _sc_api@ocelot.cul.columbia.edu
@@ -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/&quot;CUcERH0_fyp7IWA9WxFRGUw.&quot;" 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/&quot;A0AFR347eCp7IWA9WxFRF0U.&quot;" 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/&quot;D0QFQX47eCp7IWA9WxFSFks.&quot;" 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/&quot;CkAMQn47eCp7IWA9WxFSEk4.&quot;" 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/&quot;DkYHR347eCp7IWA9WxFRGEU.&quot;" 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