gdata2 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CREDITS +3 -0
- data/History.txt +0 -0
- data/Manifest.txt +15 -0
- data/README.txt +70 -0
- data/Rakefile +62 -0
- data/TODO +12 -0
- data/gdata2.gemspec +34 -0
- data/lib/gdata.rb +58 -0
- data/lib/gdata/apps/provisioning.rb +437 -0
- metadata +89 -0
data/CREDITS
ADDED
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
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
|
+
|