gdata2 0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|