provisioning-api 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +20 -0
- data/.rvmrc +47 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +25 -0
- data/README.md +80 -0
- data/Rakefile +14 -0
- data/fixtures/vcr_cassettes/create_user.yml +96 -0
- data/lib/provisioning-api.rb +882 -0
- data/lib/provisioning-api/connection.rb +47 -0
- data/lib/provisioning-api/exceptions.rb +19 -0
- data/provisioning-api.gemspec +13 -0
- data/test/test_provisioning_api.rb +32 -0
- metadata +57 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
# This is an RVM Project .rvmrc file, used to automatically load the ruby
|
4
|
+
# development environment upon cd'ing into the directory
|
5
|
+
|
6
|
+
# First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
|
7
|
+
environment_id="ruby-1.9.2-p290@provisioning-api"
|
8
|
+
|
9
|
+
#
|
10
|
+
# Uncomment following line if you want options to be set only for given project.
|
11
|
+
#
|
12
|
+
# PROJECT_JRUBY_OPTS=( --1.9 )
|
13
|
+
|
14
|
+
#
|
15
|
+
# First we attempt to load the desired environment directly from the environment
|
16
|
+
# file. This is very fast and efficient compared to running through the entire
|
17
|
+
# CLI and selector. If you want feedback on which environment was used then
|
18
|
+
# insert the word 'use' after --create as this triggers verbose mode.
|
19
|
+
#
|
20
|
+
if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
|
21
|
+
&& -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
|
22
|
+
then
|
23
|
+
\. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
|
24
|
+
|
25
|
+
if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]
|
26
|
+
then
|
27
|
+
. "${rvm_path:-$HOME/.rvm}/hooks/after_use"
|
28
|
+
fi
|
29
|
+
else
|
30
|
+
# If the environment file has not yet been created, use the RVM CLI to select.
|
31
|
+
if ! rvm --create "$environment_id"
|
32
|
+
then
|
33
|
+
echo "Failed to create RVM environment '${environment_id}'."
|
34
|
+
exit 1
|
35
|
+
fi
|
36
|
+
fi
|
37
|
+
|
38
|
+
#
|
39
|
+
# If you use an RVM gemset file to install a list of gems (*.gems), you can have
|
40
|
+
# it be automatically loaded. Uncomment the following and adjust the filename if
|
41
|
+
# necessary.
|
42
|
+
#
|
43
|
+
# filename=".gems"
|
44
|
+
# if [[ -s "$filename" ]] ; then
|
45
|
+
# rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
|
46
|
+
# fi
|
47
|
+
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
coderay (0.9.8)
|
5
|
+
fakeweb (1.3.0)
|
6
|
+
method_source (0.6.7)
|
7
|
+
ruby_parser (>= 2.3.1)
|
8
|
+
pry (0.9.7.4)
|
9
|
+
coderay (~> 0.9.8)
|
10
|
+
method_source (~> 0.6.7)
|
11
|
+
ruby_parser (>= 2.3.1)
|
12
|
+
slop (~> 2.1.0)
|
13
|
+
ruby_parser (2.3.1)
|
14
|
+
sexp_processor (~> 3.0)
|
15
|
+
sexp_processor (3.0.8)
|
16
|
+
slop (2.1.0)
|
17
|
+
vcr (1.11.3)
|
18
|
+
|
19
|
+
PLATFORMS
|
20
|
+
ruby
|
21
|
+
|
22
|
+
DEPENDENCIES
|
23
|
+
fakeweb
|
24
|
+
pry
|
25
|
+
vcr
|
data/README.md
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
Google apps provisioning API ruby library
|
2
|
+
========================================
|
3
|
+
|
4
|
+
This is a copy of the Google Apps provisioning API taken from http://code.google.com/p/gdatav2rubyclientlib/ v 1.2 (latest)
|
5
|
+
|
6
|
+
BEFORE USE Enable the API on Google Admin Panel
|
7
|
+
=================================================
|
8
|
+
|
9
|
+
Domain Settings -> User Settings -> Enable Provisionin API
|
10
|
+
|
11
|
+
https://www.google.com/a/cpanel/[YOUR_DOMAIN.com]/DomainSettingsUserSettings
|
12
|
+
|
13
|
+
Example
|
14
|
+
=========
|
15
|
+
|
16
|
+
#!/usr/bin/ruby
|
17
|
+
require 'gappsprovisioning/provisioningapi'
|
18
|
+
include GAppsProvisioning
|
19
|
+
adminuser = "root@mydomain.com"
|
20
|
+
password = "PaSsWo4d!"
|
21
|
+
myapps = ProvisioningApi.new(adminuser,password)
|
22
|
+
|
23
|
+
new_user = myapps.create_user("jsmith", "john", "smith", "12345678", nil, "2048")
|
24
|
+
puts new_user.family_name
|
25
|
+
puts new_user.given_name
|
26
|
+
|
27
|
+
Want to update a user ?
|
28
|
+
|
29
|
+
user = myapps.retrieve_user('jsmith')
|
30
|
+
user_updated = myapps.update_user(user.username, user.given_name, user.family_name, nil, nil, "true")
|
31
|
+
|
32
|
+
Want to add an alias or nickname ?
|
33
|
+
|
34
|
+
new_nickname = myapps.create_nickname("jsmith", "john.smith")
|
35
|
+
|
36
|
+
Want to add an email forwarding (thanks to Scott Jungling) ?
|
37
|
+
|
38
|
+
new_forwarding = myapps.create_email_forwarding("jsmith", "brenda@yourdomain.com", "KEEP")
|
39
|
+
|
40
|
+
Want to manage groups ? (i.e. mailing lists)
|
41
|
+
|
42
|
+
new_group = myapps.create_group("sales-dep", ['Sales Departement'])
|
43
|
+
new_member = myapps.add_member_to_group("jsmith", "sales-dep")
|
44
|
+
new_owner = myapps.add_owner_to_group("jsmith", "sales-dep")
|
45
|
+
# (ATTENTION: a owner is added only if it's already member of the group!)
|
46
|
+
|
47
|
+
Want to handle errors ?
|
48
|
+
|
49
|
+
begin
|
50
|
+
user = myapps.retrieve_user('noone')
|
51
|
+
puts "givenName : "+user.given_name, "familyName : "+user.family_name, "username : "+user.username
|
52
|
+
puts "admin ? : "+user.admin
|
53
|
+
rescue GDataError => e
|
54
|
+
puts "errorcode = "+e.code, "input : "+e.input, "reason : "+e.reason
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
Character Usage
|
59
|
+
===============
|
60
|
+
|
61
|
+
- Usernames may contain letters (a-z), numbers (0-9), dashes (-), underscores (_), and periods (.), and may not contain an equal sign (=) or brackets (<,>).
|
62
|
+
They can't contain more than one period in a row.
|
63
|
+
|
64
|
+
- Passwords may contain any combination of characters, but a minimum of 8 characters is required.
|
65
|
+
|
66
|
+
- First and last names support unicode/UTF-8 characters, and may contain spaces, letters (a-z), numbers (0-9), dashes (-), forward slashes (/), and periods (.), with a maximum of 40 characters.
|
67
|
+
|
68
|
+
-Characters that cannot be part of a name include: !, #, $, %, &, (, ), *, +, /, ?, \, ^, |, ~
|
69
|
+
|
70
|
+
Testing
|
71
|
+
=========
|
72
|
+
|
73
|
+
Google API testing is hard. There are multiple server side rules that
|
74
|
+
make testing hard, such as deleting a user and creating it back requires
|
75
|
+
you to wait for 5 days.
|
76
|
+
|
77
|
+
Instead we simply use VCR to verify that code interprets correctly and
|
78
|
+
that the codes are being made. If you want to "really" test the API you
|
79
|
+
need a username and password for a domain to run your tests.
|
80
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
---
|
2
|
+
- !ruby/struct:VCR::HTTPInteraction
|
3
|
+
request: !ruby/struct:VCR::Request
|
4
|
+
method: :post
|
5
|
+
uri: https://apps-apis.google.com:443/accounts/ClientLogin
|
6
|
+
body: !!null
|
7
|
+
headers:
|
8
|
+
content-type:
|
9
|
+
- application/x-www-form-urlencoded
|
10
|
+
content-length:
|
11
|
+
- '75'
|
12
|
+
response: !ruby/struct:VCR::Response
|
13
|
+
status: !ruby/struct:VCR::ResponseStatus
|
14
|
+
code: 200
|
15
|
+
message: OK
|
16
|
+
headers:
|
17
|
+
content-type:
|
18
|
+
- text/plain
|
19
|
+
cache-control:
|
20
|
+
- no-cache, no-store
|
21
|
+
pragma:
|
22
|
+
- no-cache
|
23
|
+
expires:
|
24
|
+
- Mon, 01-Jan-1990 00:00:00 GMT
|
25
|
+
date:
|
26
|
+
- Sat, 26 Nov 2011 20:35:13 GMT
|
27
|
+
x-content-type-options:
|
28
|
+
- nosniff
|
29
|
+
x-xss-protection:
|
30
|
+
- 1; mode=block
|
31
|
+
content-length:
|
32
|
+
- '1010'
|
33
|
+
server:
|
34
|
+
- GSE
|
35
|
+
body: ! 'SID=DQAAAOcAAABGChSuJCFvcdA-phg8w37dgl7m125nCpbJSMsqlGTD8nr-T5fqvL4VJJUPQfgOLwArzuJ_v5r3r0irFYlp75W7CuwVVIZcGVh3NinwQuK1C2b1LoDRXPYQAksj0FHf_-M4La-t3sx9Psz9KVZS0_sBRnaLACaX613iyTQQhih75XdF_pPJEAk2i-FODvFlywaVITn6aft6Q15ba2Ns3pXBxHC2xmNtXTD_A-6ItDo5h6ged6uE_tMUOI37hpmT56mqHGM2MKeKS1FWltKG04Q7a4IqAFtbOqIfm7NQng2OGTH8n35QamnvpNClsHXj-LU
|
36
|
+
|
37
|
+
LSID=DQAAAOgAAACmOK2Tz82DjgQCZsSyl3BBXyBrE_FRnJ1kX_b2--FxR41rFaDLrF7vZCVQRbYj6umr8m2k16XSHyRGC0OHAEN4ordG7pi3gVFePuPLGStA_0TXdR6kAD0E8XeuEiEo4jU2QOZUhNdUEsYJ2rmvyfCaieKPq28xy2jhxlni3HKe4ys6kCV9nslCcvpmgXGPtTe1MJJ_GhRgIwfh3Xp9JsP87tijHw7FK8n5rhZCuxtYWlMXZGXuTtWD_NsqcJ8rRLedk6KAsIxTFH_X9IC-3CRvRacRk29Wc6Ccv2YEMQWm5qq9WgrXkTcoQzdt-aY1JM0
|
38
|
+
|
39
|
+
Auth=DQAAAOkAAACmOK2Tz82DjgQCZsSyl3BBXyBrE_FRnJ1kX_b2--FxR41rFaDLrF7vZCVQRbYj6uluQDfTwKQVZT7NBybM4B5pq3iIBq-B7igOAeC3hfBQGPfE8Q5Lyu9qoAXLYOOkRjNBfydACgdsJxGbCZoggW3Amkh1Js4awD-DXSOVepBGOYiF8hCYiLu3LlwMt1e6EzTbVyOlCyB8aa1HPZDvHTh0VDNBSGSQZtl6dUjp4z1rOfutoNhpl0niywLX974lp0nXm4oqWH0a2ASv1vlZ2t_wbDMe3EVWI42N_DBMCP7t6jscweCZZhbREpjUEcEvgQQ
|
40
|
+
|
41
|
+
'
|
42
|
+
http_version: '1.1'
|
43
|
+
- !ruby/struct:VCR::HTTPInteraction
|
44
|
+
request: !ruby/struct:VCR::Request
|
45
|
+
method: :post
|
46
|
+
uri: https://apps-apis.google.com:443/a/feeds/authysec.com/user/2.0
|
47
|
+
body: !!null
|
48
|
+
headers:
|
49
|
+
content-type:
|
50
|
+
- application/atom+xml
|
51
|
+
authorization:
|
52
|
+
- GoogleLogin auth=DQAAAOkAAACmOK2Tz82DjgQCZsSyl3BBXyBrE_FRnJ1kX_b2--FxR41rFaDLrF7vZCVQRbYj6uluQDfTwKQVZT7NBybM4B5pq3iIBq-B7igOAeC3hfBQGPfE8Q5Lyu9qoAXLYOOkRjNBfydACgdsJxGbCZoggW3Amkh1Js4awD-DXSOVepBGOYiF8hCYiLu3LlwMt1e6EzTbVyOlCyB8aa1HPZDvHTh0VDNBSGSQZtl6dUjp4z1rOfutoNhpl0niywLX974lp0nXm4oqWH0a2ASv1vlZ2t_wbDMe3EVWI42N_DBMCP7t6jscweCZZhbREpjUEcEvgQQ
|
53
|
+
content-length:
|
54
|
+
- '473'
|
55
|
+
response: !ruby/struct:VCR::Response
|
56
|
+
status: !ruby/struct:VCR::ResponseStatus
|
57
|
+
code: 201
|
58
|
+
message: Created
|
59
|
+
headers:
|
60
|
+
content-type:
|
61
|
+
- application/atom+xml; charset=UTF-8
|
62
|
+
expires:
|
63
|
+
- Sat, 26 Nov 2011 20:35:17 GMT
|
64
|
+
date:
|
65
|
+
- Sat, 26 Nov 2011 20:35:17 GMT
|
66
|
+
cache-control:
|
67
|
+
- private, max-age=0, must-revalidate, no-transform
|
68
|
+
vary:
|
69
|
+
- Accept, X-GData-Authorization, GData-Version
|
70
|
+
gdata-version:
|
71
|
+
- '1.0'
|
72
|
+
location:
|
73
|
+
- https://apps-apis.google.com/a/feeds/authysec.com/user/2.0/josmith
|
74
|
+
content-location:
|
75
|
+
- https://apps-apis.google.com/a/feeds/authysec.com/user/2.0/josmith
|
76
|
+
x-content-type-options:
|
77
|
+
- nosniff
|
78
|
+
x-frame-options:
|
79
|
+
- SAMEORIGIN
|
80
|
+
x-xss-protection:
|
81
|
+
- 1; mode=block
|
82
|
+
server:
|
83
|
+
- GSE
|
84
|
+
transfer-encoding:
|
85
|
+
- chunked
|
86
|
+
body: <?xml version='1.0' encoding='UTF-8'?><entry xmlns='http://www.w3.org/2005/Atom'
|
87
|
+
xmlns:apps='http://schemas.google.com/apps/2006' xmlns:gd='http://schemas.google.com/g/2005'><id>https://apps-apis.google.com/a/feeds/authysec.com/user/2.0/josmith</id><updated>1970-01-01T00:00:00.000Z</updated><category
|
88
|
+
scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/apps/2006#user'/><title
|
89
|
+
type='text'>josmith</title><link rel='self' type='application/atom+xml' href='https://apps-apis.google.com/a/feeds/authysec.com/user/2.0/josmith'/><link
|
90
|
+
rel='edit' type='application/atom+xml' href='https://apps-apis.google.com/a/feeds/authysec.com/user/2.0/josmith'/><apps:login
|
91
|
+
userName='josmith' suspended='false' ipWhitelisted='false' admin='false' changePasswordAtNextLogin='true'
|
92
|
+
agreedToTerms='false'/><apps:quota limit='7168'/><apps:name familyName='smith'
|
93
|
+
givenName='john'/><gd:feedLink rel='http://schemas.google.com/apps/2006#user.nicknames'
|
94
|
+
href='https://apps-apis.google.com/a/feeds/authysec.com/nickname/2.0?username=josmith'/><gd:feedLink
|
95
|
+
rel='http://schemas.google.com/apps/2006#user.emailLists' href='https://apps-apis.google.com/a/feeds/authysec.com/emailList/2.0?recipient=josmith%40authysec.com'/></entry>
|
96
|
+
http_version: '1.1'
|
@@ -0,0 +1,882 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# == Google Apps Provisioning API client library
|
3
|
+
#
|
4
|
+
# This library allows you to manage your domain (accounts, email lists, aliases) within your Ruby code.
|
5
|
+
# It's based on the GDATA provisioning API v2.0.
|
6
|
+
# Reference : http://code.google.com/apis/apps/gdata_provisioning_api_v2.0_reference.html.
|
7
|
+
#
|
8
|
+
# All the public methods with _ruby_style_ names are aliased with _javaStyle_ names. Ex : create_user and createUser.
|
9
|
+
#
|
10
|
+
# Notice : because it uses REXML, your script using this library MUST be encoded in unicode (UTF-8).
|
11
|
+
#
|
12
|
+
# == Examples
|
13
|
+
#
|
14
|
+
# #!/usr/bin/ruby
|
15
|
+
# require 'provisioning-api/provisioningapi'
|
16
|
+
# include provisioning-api
|
17
|
+
# adminuser = "root@mydomain.com"
|
18
|
+
# password = "PaSsWo4d!"
|
19
|
+
# myapps = ProvisioningApi.new(adminuser,password)
|
20
|
+
# (see examples in ProvisioningApi.new documentation for handling proxies)
|
21
|
+
#
|
22
|
+
# new_user = myapps.create_user("jsmith", "john", "smith", "secret", nil, "2048")
|
23
|
+
# puts new_user.family_name
|
24
|
+
# puts new_user.given_name
|
25
|
+
#
|
26
|
+
# Want to update a user ?
|
27
|
+
#
|
28
|
+
# user = myapps.retrieve_user('jsmith')
|
29
|
+
# user_updated = myapps.update_user(user.username, user.given_name, user.family_name, nil, nil, "true")
|
30
|
+
#
|
31
|
+
# Want to add an alias or nickname ?
|
32
|
+
#
|
33
|
+
# new_nickname = myapps.create_nickname("jsmith", "john.smith")
|
34
|
+
#
|
35
|
+
# Want to manage groups ? (i.e. mailing lists)
|
36
|
+
#
|
37
|
+
# new_group = myapps.create_group("sales-dep", ['Sales Departement'])
|
38
|
+
# new_member = myapps.add_member_to_group("jsmith", "sales-dep")
|
39
|
+
# new_owner = myapps.add_owner_to_group("jsmith", "sales-dep")
|
40
|
+
# (ATTENTION: an owner is added only if it's already member of the group!)
|
41
|
+
#
|
42
|
+
# Want to handle errors ?
|
43
|
+
#
|
44
|
+
# begin
|
45
|
+
# user = myapps.retrieve_user('noone')
|
46
|
+
# puts "givenName : "+user.given_name, "familyName : "+user.family_name, "username : "+user.username"
|
47
|
+
# puts "admin ? : "+user.admin
|
48
|
+
# rescue GDataError => e
|
49
|
+
# puts "errorcode = " +e.code, "input : "+e.input, "reason : "+e.reason
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# Email lists (deprecated) ?
|
53
|
+
#
|
54
|
+
# new_list = myapps.create_email_list("sales-dep")
|
55
|
+
# new_address = myapps.add_address_to_email_list("sales-dep", "bibi@ruby-forge.org")
|
56
|
+
#
|
57
|
+
# All methods described in the provisioning-api::ProvisioningApi class documentation.
|
58
|
+
#
|
59
|
+
# Authors :: Jérôme Bousquié, Roberto Cerigato
|
60
|
+
# Ruby version :: from 1.8.6
|
61
|
+
# Licence :: Apache Licence, version 2
|
62
|
+
#
|
63
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
64
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
65
|
+
# the License at
|
66
|
+
#
|
67
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
68
|
+
#
|
69
|
+
# Unless required by applicable law or agreed to in writing, software
|
70
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
71
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
72
|
+
# License for the specific language governing permissions and limitations under
|
73
|
+
# the License.
|
74
|
+
#
|
75
|
+
|
76
|
+
require 'cgi'
|
77
|
+
require 'rexml/document'
|
78
|
+
|
79
|
+
require 'provisioning-api/connection'
|
80
|
+
require 'provisioning-api/exceptions'
|
81
|
+
|
82
|
+
include REXML
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
module GAppsProvisioning #:nodoc:
|
87
|
+
|
88
|
+
# =Administrative object for accessing your domain
|
89
|
+
# Examples
|
90
|
+
#
|
91
|
+
# adminuser = "root@mydomain.com"
|
92
|
+
# password = "PaSsWo4d!"
|
93
|
+
# myapps = ProvisioningApi.new(adminuser,password)
|
94
|
+
# (see examples in ProvisioningApi.new documentation for handling proxies)
|
95
|
+
#
|
96
|
+
# new_user = myapps.create_user("jsmith", "john", "smith", "secret", nil, "2048")
|
97
|
+
# puts new_user.family_name
|
98
|
+
# puts new_user.given_name
|
99
|
+
#
|
100
|
+
# Want to update a user ?
|
101
|
+
#
|
102
|
+
# user = myapps.retrieve_user('jsmith')
|
103
|
+
# user_updated = myapps.update_user(user.username, user.given_name, user.family_name, nil, nil, "true")
|
104
|
+
#
|
105
|
+
# Want to add an alias or nickname ?
|
106
|
+
#
|
107
|
+
# new_nickname = myapps.create_nickname("jsmith", "john.smith")
|
108
|
+
#
|
109
|
+
# Want to manage groups ? (i.e. mailing lists)
|
110
|
+
#
|
111
|
+
# new_group = myapps.create_group("sales-dep", ['Sales Departement'])
|
112
|
+
# new_member1 = myapps.add_member_to_group("john.doe@somedomain.com", "sales-dep")
|
113
|
+
# new_member2 = myapps.add_member_to_group("jsmith", "sales-dep")
|
114
|
+
# new_owner = myapps.add_owner_to_group("jsmith", "sales-dep")
|
115
|
+
# (ATTENTION: an owner is added only if it's already member of the group!)
|
116
|
+
#
|
117
|
+
#
|
118
|
+
# Want to handle errors ?
|
119
|
+
#
|
120
|
+
# begin
|
121
|
+
# user = myapps.retrieve_user('noone')
|
122
|
+
# puts "givenName : "+user.given_name, "familyName : "+user.family_name, "username : "+user.username"
|
123
|
+
# puts "admin ? : "+user.admin
|
124
|
+
# rescue GDataError => e
|
125
|
+
# puts "errorcode = " +e.code, "input : "+e.input, "reason : "+e.reason
|
126
|
+
# end
|
127
|
+
#
|
128
|
+
#
|
129
|
+
|
130
|
+
|
131
|
+
|
132
|
+
class ProvisioningApi
|
133
|
+
@@google_host = 'apps-apis.google.com'
|
134
|
+
@@google_port = 443
|
135
|
+
# authentication token, valid up to 24 hours after the last connection
|
136
|
+
attr_reader :token
|
137
|
+
|
138
|
+
|
139
|
+
# Creates a new ProvisioningApi object
|
140
|
+
#
|
141
|
+
# mail : Google Apps domain administrator e-mail (string)
|
142
|
+
# passwd : Google Apps domain administrator password (string)
|
143
|
+
# proxy : (optional) host name, or IP, of the proxy (string)
|
144
|
+
# proxy_port : (optional) proxy port number (numeric)
|
145
|
+
# proxy_user : (optional) login for authenticated proxy only (string)
|
146
|
+
# proxy_passwd : (optional) password for authenticated proxy only (string)
|
147
|
+
#
|
148
|
+
# The domain name is extracted from the mail param value.
|
149
|
+
#
|
150
|
+
# Examples :
|
151
|
+
# standard : no proxy
|
152
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
153
|
+
# proxy :
|
154
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd','domain.proxy.com',8080)
|
155
|
+
# authenticated proxy :
|
156
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd','domain.proxy.com',8080,'foo','bAr')
|
157
|
+
def initialize(mail, passwd, proxy=nil, proxy_port=nil, proxy_user=nil, proxy_passwd=nil)
|
158
|
+
domain = mail.split('@')[1]
|
159
|
+
@action = setup_actions(domain)
|
160
|
+
conn = Connection.new(@@google_host, @@google_port, proxy, proxy_port, proxy_user, proxy_passwd)
|
161
|
+
@connection = conn
|
162
|
+
@token = login(mail, passwd)
|
163
|
+
@headers = {'Content-Type'=>'application/atom+xml', 'Authorization'=> 'GoogleLogin auth='+token}
|
164
|
+
return @connection
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
|
169
|
+
# Returns a UserEntry instance from a username
|
170
|
+
# ex :
|
171
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
172
|
+
# user = myapps.retrieve_user('jsmith')
|
173
|
+
# puts "givenName : "+user.given_name
|
174
|
+
# puts "familyName : "+user.family_name
|
175
|
+
def retrieve_user(username)
|
176
|
+
xml_response = request(:user_retrieve, username, @headers)
|
177
|
+
user_entry = UserEntry.new(xml_response.elements["entry"])
|
178
|
+
end
|
179
|
+
|
180
|
+
# 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.
|
181
|
+
# ex :
|
182
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
183
|
+
# list= myapps.retrieve_all_users
|
184
|
+
# list.each{ |user| puts user.username}
|
185
|
+
# puts 'nb users : ',list.size
|
186
|
+
def retrieve_all_users
|
187
|
+
response = request(:user_retrieve_all,nil,@headers)
|
188
|
+
user_feed = Feed.new(response.elements["feed"], UserEntry)
|
189
|
+
user_feed = add_next_feeds(user_feed, response, UserEntry)
|
190
|
+
end
|
191
|
+
|
192
|
+
# Returns a UserEntry array populated with 100 users, starting from a username
|
193
|
+
# ex :
|
194
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
195
|
+
# list= myapps.retrieve_page_of_users("jsmtih")
|
196
|
+
# list.each{ |user| puts user.username}
|
197
|
+
def retrieve_page_of_users(start_username)
|
198
|
+
param='?startUsername='+start_username
|
199
|
+
response = request(:user_retrieve_all,param,@headers)
|
200
|
+
user_feed = Feed.new(response.elements["feed"], UserEntry)
|
201
|
+
end
|
202
|
+
|
203
|
+
# Creates an account in your domain, returns a UserEntry instance
|
204
|
+
# params :
|
205
|
+
# username, given_name, family_name and password are required
|
206
|
+
# passwd_hash_function (optional) : nil (default) or "SHA-1"
|
207
|
+
# quota (optional) : nil (default) or integer for limit in MB
|
208
|
+
# ex :
|
209
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
210
|
+
# user = myapps.create('jsmith', 'John', 'Smith', 'p455wD')
|
211
|
+
#
|
212
|
+
# 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.
|
213
|
+
def create_user(username, given_name, family_name, password, passwd_hash_function=nil, quota=nil)
|
214
|
+
msg = RequestMessage.new
|
215
|
+
msg.about_login(username,password,passwd_hash_function,"false","false", "true")
|
216
|
+
msg.about_name(family_name, given_name)
|
217
|
+
msg.about_quota(quota.to_s) if quota
|
218
|
+
response = request(:user_create,nil,@headers, msg.to_s)
|
219
|
+
user_entry = UserEntry.new(response.elements["entry"])
|
220
|
+
end
|
221
|
+
|
222
|
+
# Updates an account in your domain, returns a UserEntry instance
|
223
|
+
# params :
|
224
|
+
# username is required and can't be updated.
|
225
|
+
# given_name and family_name are required, may be updated.
|
226
|
+
# if set to nil, every other parameter won't update the attribute.
|
227
|
+
# passwd_hash_function : string "SHA-1", "MD5" or nil (default)
|
228
|
+
# admin : string "true" or string "false" or nil (no boolean : true or false).
|
229
|
+
# suspended : string "true" or string "false" or nil (no boolean : true or false)
|
230
|
+
# change_passwd : string "true" or string "false" or nil (no boolean : true or false)
|
231
|
+
# quota : limit en MB, ex : string "2048"
|
232
|
+
# ex :
|
233
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
234
|
+
# user = myapps.update('jsmith', 'John', 'Smith', nil, nil, "true", nil, "true", nil)
|
235
|
+
# puts user.admin => "true"
|
236
|
+
def update_user(username, given_name, family_name, password=nil, passwd_hash_function=nil, admin=nil, suspended=nil, changepasswd=nil, quota=nil)
|
237
|
+
msg = RequestMessage.new
|
238
|
+
msg.about_login(username,password,passwd_hash_function,admin,suspended, changepasswd)
|
239
|
+
msg.about_name(family_name, given_name)
|
240
|
+
msg.about_quota(quota) if quota
|
241
|
+
msg.add_path('https://'+@@google_host+@action[:user_update][:path]+username)
|
242
|
+
response = request(:user_update,username,@headers, msg.to_s)
|
243
|
+
user_entry = UserEntry.new(response.elements["entry"])
|
244
|
+
end
|
245
|
+
|
246
|
+
# Renames a user, returns a UserEntry instance
|
247
|
+
# ex :
|
248
|
+
#
|
249
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
250
|
+
# user = myapps.rename_user('jsmith','jdoe')
|
251
|
+
#
|
252
|
+
# It is recommended to log out rhe user from all browser sessions and service before renaming.
|
253
|
+
# Once renamed, the old username becomes a nickname of the new username.
|
254
|
+
# Note from Google: Google Talk will lose all remembered chat invitations after renaming.
|
255
|
+
# The user must request permission to chat with friends again.
|
256
|
+
# 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.
|
257
|
+
# To remove the nickname, you should issue an HTTP DELETE to the nicknames feed after renaming.
|
258
|
+
def rename_user(username, new_username)
|
259
|
+
msg = RequestMessage.new
|
260
|
+
msg.about_login(new_username)
|
261
|
+
msg.add_path('https://'+@@google_host+@action[:user_rename][:path]+username)
|
262
|
+
response = request(:user_update,username,@headers, msg.to_s)
|
263
|
+
end
|
264
|
+
|
265
|
+
# Suspends an account in your domain, returns a UserEntry instance
|
266
|
+
# ex :
|
267
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
268
|
+
# user = myapps.suspend('jsmith')
|
269
|
+
# puts user.suspended => "true"
|
270
|
+
def suspend_user(username)
|
271
|
+
msg = RequestMessage.new
|
272
|
+
msg.about_login(username,nil,nil,nil,"true")
|
273
|
+
msg.add_path('https://'+@@google_host+@action[:user_update][:path]+username)
|
274
|
+
response = request(:user_update,username,@headers, msg.to_s)
|
275
|
+
user_entry = UserEntry.new(response.elements["entry"])
|
276
|
+
end
|
277
|
+
|
278
|
+
# Restores a suspended account in your domain, returns a UserEntry instance
|
279
|
+
# ex :
|
280
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
281
|
+
# user = myapps.restore('jsmith')
|
282
|
+
# puts user.suspended => "false"
|
283
|
+
def restore_user(username)
|
284
|
+
msg = RequestMessage.new
|
285
|
+
msg.about_login(username,nil,nil,nil,"false")
|
286
|
+
msg.add_path('https://'+@@google_host+@action[:user_update][:path]+username)
|
287
|
+
response = request(:user_update,username,@headers, msg.to_s)
|
288
|
+
user_entry = UserEntry.new(response.elements["entry"])
|
289
|
+
end
|
290
|
+
|
291
|
+
# Deletes an account in your domain
|
292
|
+
# ex :
|
293
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
294
|
+
# myapps.delete('jsmith')
|
295
|
+
def delete_user(username)
|
296
|
+
response = request(:user_delete,username,@headers)
|
297
|
+
end
|
298
|
+
|
299
|
+
# Returns a NicknameEntry instance from a nickname
|
300
|
+
# ex :
|
301
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
302
|
+
# nickname = myapps.retrieve_nickname('jsmith')
|
303
|
+
# puts "login : "+nickname.login
|
304
|
+
def retrieve_nickname(nickname)
|
305
|
+
xml_response = request(:nickname_retrieve, nickname, @headers)
|
306
|
+
nickname_entry = NicknameEntry.new(xml_response.elements["entry"])
|
307
|
+
end
|
308
|
+
|
309
|
+
# Returns a NicknameEntry array from a username
|
310
|
+
# ex : lists jsmith's nicknames
|
311
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
312
|
+
# mynicks = myapps.retrieve('jsmith')
|
313
|
+
# mynicks.each {|nick| puts nick.nickname }
|
314
|
+
def retrieve_nicknames(username)
|
315
|
+
xml_response = request(:nickname_retrieve_all_for_user, username, @headers)
|
316
|
+
nicknames_feed = Feed.new(xml_response.elements["feed"], NicknameEntry)
|
317
|
+
nicknames_feed = add_next_feeds(nicknames_feed, xml_response, NicknameEntry)
|
318
|
+
end
|
319
|
+
|
320
|
+
# Returns a NicknameEntry array for the whole domain. May take a while depending on the number of users in your domain.
|
321
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
322
|
+
# allnicks = myapps.retrieve_all_nicknames
|
323
|
+
# allnicks.each {|nick| puts nick.nickname }
|
324
|
+
def retrieve_all_nicknames
|
325
|
+
xml_response = request(:nickname_retrieve_all_in_domain, nil, @headers)
|
326
|
+
nicknames_feed = Feed.new(xml_response.elements["feed"], NicknameEntry)
|
327
|
+
nicknames_feed = add_next_feeds(nicknames_feed, xml_response, NicknameEntry)
|
328
|
+
end
|
329
|
+
|
330
|
+
# Creates a nickname for the username in your domain and returns a NicknameEntry instance
|
331
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
332
|
+
# mynewnick = myapps.create_nickname('jsmith', 'john.smith')
|
333
|
+
def create_nickname(username,nickname)
|
334
|
+
msg = RequestMessage.new
|
335
|
+
msg.about_login(username)
|
336
|
+
msg.about_nickname(nickname)
|
337
|
+
response = request(:nickname_create,nil,@headers, msg.to_s)
|
338
|
+
nickname_entry = NicknameEntry.new(response.elements["entry"])
|
339
|
+
end
|
340
|
+
|
341
|
+
# Deletes the nickname in your domain
|
342
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
343
|
+
# myapps.delete_nickname('john.smith')
|
344
|
+
def delete_nickname(nickname)
|
345
|
+
response = request(:nickname_delete,nickname,@headers)
|
346
|
+
end
|
347
|
+
|
348
|
+
# Returns a NicknameEntry array populated with 100 nicknames, starting from a nickname
|
349
|
+
# ex :
|
350
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
351
|
+
# list= myapps.retrieve_page_of_nicknames("joe")
|
352
|
+
# list.each{ |nick| puts nick.login}
|
353
|
+
def retrieve_page_of_nicknames(start_nickname)
|
354
|
+
param='?startNickname='+start_nickname
|
355
|
+
xml_response = request(:nickname_retrieve_all_in_domain, param, @headers)
|
356
|
+
nicknames_feed = Feed.new(xml_response.elements["feed"], NicknameEntry)
|
357
|
+
end
|
358
|
+
|
359
|
+
# Deprecated. Please use Group management instead.
|
360
|
+
def retrieve_email_lists(email_adress)
|
361
|
+
puts("retrieve_email_lists : deprecated. Please use Group management instead.")
|
362
|
+
end
|
363
|
+
|
364
|
+
# Deprecated. Please use Group management instead.
|
365
|
+
def retrieve_all_email_lists
|
366
|
+
puts("retrieve_all_email_lists : deprecated. Please use Group management instead.")
|
367
|
+
end
|
368
|
+
|
369
|
+
# Deprecated. Please use Group management instead.
|
370
|
+
def retrieve_page_of_email_lists(start_listname)
|
371
|
+
puts("retrieve_page_of_email_lists : deprecated. Please use Group management instead.")
|
372
|
+
end
|
373
|
+
|
374
|
+
# Deprecated. Please use Group management instead.
|
375
|
+
def create_email_list(name)
|
376
|
+
puts("create_email_list : deprecated. Please use Group management instead.")
|
377
|
+
end
|
378
|
+
|
379
|
+
# Deprecated. Please use Group management instead.
|
380
|
+
def delete_email_list(name)
|
381
|
+
puts("delete_email_list : deprecated. Please use Group management instead.")
|
382
|
+
end
|
383
|
+
|
384
|
+
# Deprecated. Please use Group management instead.
|
385
|
+
def retrieve_all_recipients(email_list)
|
386
|
+
puts("retrieve_all_recipients : deprecated. Please use Group management instead.")
|
387
|
+
end
|
388
|
+
|
389
|
+
# Deprecated. Please use Group management instead.
|
390
|
+
def retrieve_page_of_recipients(email_list, start_recipient)
|
391
|
+
puts("Deprecated. Please use Group management instead.")
|
392
|
+
end
|
393
|
+
|
394
|
+
# Deprecated. Please use Group management instead.
|
395
|
+
def add_address_to_email_list(email_list,address)
|
396
|
+
puts("add_address_to_email_list : deprecated. Please use Group management instead.")
|
397
|
+
end
|
398
|
+
|
399
|
+
# Deprecated. Please use Group management instead.
|
400
|
+
def remove_address_from_email_list(address,email_list)
|
401
|
+
puts("remove_address_from_email_list : deprecated. Please use Group management instead.")
|
402
|
+
end
|
403
|
+
|
404
|
+
# Creates a group in your domain and returns a GroupEntry (ATTENTION: the group name is necessary!).
|
405
|
+
# ex :
|
406
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
407
|
+
# group= myapps.create_group("mygroup", ["My Group name", "My Group description", "<emailPermission>"])
|
408
|
+
def create_group(group_id, properties)
|
409
|
+
msg = RequestMessage.new
|
410
|
+
msg.about_group(group_id, properties)
|
411
|
+
response = request(:group_create, nil, @headers, msg.to_s)
|
412
|
+
group_entry = GroupEntry.new(response.elements["entry"])
|
413
|
+
end
|
414
|
+
|
415
|
+
# Updates a group in your domain and returns a GroupEntry (ATTENTION: the group name is necessary!).
|
416
|
+
# ex :
|
417
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
418
|
+
# group= myapps.update_group("mygroup", ["My Group name", "My Group description", "<emailPermission>"])
|
419
|
+
def update_group(group_id, properties)
|
420
|
+
msg = RequestMessage.new
|
421
|
+
msg.about_group(group_id, properties)
|
422
|
+
response = request(:group_update, group_id, @headers, msg.to_s)
|
423
|
+
group_entry = GroupEntry.new(response.elements["entry"])
|
424
|
+
end
|
425
|
+
|
426
|
+
# Deletes a group in your domain.
|
427
|
+
# ex :
|
428
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
429
|
+
# myapps.delete_group("mygroup")
|
430
|
+
def delete_group(group_id)
|
431
|
+
response = request(:group_delete,group_id,@headers)
|
432
|
+
end
|
433
|
+
|
434
|
+
# Returns a GroupEntry array for a particular member of the domain (ATTENTION: it doesn't work for members of other domains!).
|
435
|
+
# The user parameter can be a complete email address or can be written without "@mydomain.com".
|
436
|
+
# ex :
|
437
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
438
|
+
# mylists = myapps.retrieve_groups('jsmith') # you can search for 'jsmith@mydomain.com' too
|
439
|
+
# mylists.each {|list| puts list.group_id }
|
440
|
+
def retrieve_groups(user)
|
441
|
+
xml_response = request(:groups_retrieve, user, @headers)
|
442
|
+
list_feed = Feed.new(xml_response.elements["feed"], GroupEntry)
|
443
|
+
list_feed = add_next_feeds(list_feed, xml_response, GroupEntry)
|
444
|
+
end
|
445
|
+
|
446
|
+
# Returns a GroupEntry array for the whole domain.
|
447
|
+
# ex :
|
448
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
449
|
+
# all_lists = myapps.retrieve_all_groups
|
450
|
+
# all_lists.each {|list| puts list.group_id }
|
451
|
+
def retrieve_all_groups
|
452
|
+
xml_response = request(:all_groups_retrieve, nil, @headers)
|
453
|
+
list_feed = Feed.new(xml_response.elements["feed"], GroupEntry)
|
454
|
+
list_feed = add_next_feeds(list_feed, xml_response, GroupEntry)
|
455
|
+
end
|
456
|
+
|
457
|
+
# Adds an email address (user or group) to a mailing list in your domain and returns a MemberEntry instance.
|
458
|
+
# You can add addresses from other domains to your mailing list. Omit "@mydomain.com" in the group name.
|
459
|
+
# ex :
|
460
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
461
|
+
# new_member = myapps.add_member_to_group('example@otherdomain.com', 'mygroup')
|
462
|
+
def add_member_to_group(email_address, group_id)
|
463
|
+
msg = RequestMessage.new
|
464
|
+
msg.about_member(email_address)
|
465
|
+
response = request(:membership_add, group_id+'/member', @headers, msg.to_s)
|
466
|
+
member_entry = MemberEntry.new(response.elements["entry"])
|
467
|
+
end
|
468
|
+
|
469
|
+
# Removes an email address (user or group) from a mailing list. Omit "@mydomain.com" in the group name.
|
470
|
+
# ex :
|
471
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
472
|
+
# myapps.remove_member_from_group('example@otherdomain.com', 'mygroup')
|
473
|
+
def remove_member_from_group(email_address, group_id)
|
474
|
+
response = request(:membership_remove, group_id+'/member/'+email_address,@headers)
|
475
|
+
end
|
476
|
+
|
477
|
+
# Returns true if the email address (user or group) is member of the group, false otherwise.
|
478
|
+
# ex :
|
479
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
480
|
+
# boolean = myapps.is_member('example@otherdomain.com', 'mylist')
|
481
|
+
def is_member(email_address, group_id)
|
482
|
+
xml_response = request(:membership_confirm, group_id+'/member/'+email_address, @headers)
|
483
|
+
# if the email_address is not member of the group, an error is raised, otherwise true is returned
|
484
|
+
return true
|
485
|
+
|
486
|
+
rescue GDataError => e
|
487
|
+
return false if e.reason.eql?("EntityDoesNotExist")
|
488
|
+
end
|
489
|
+
|
490
|
+
# Returns a MemberEntry array with the members of a group.
|
491
|
+
# ex :
|
492
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
493
|
+
# list = myapps.retrieve_all_members('mygroup')
|
494
|
+
# lists.each {|list| puts list.member_id }
|
495
|
+
def retrieve_all_members(group_id)
|
496
|
+
xml_response = request(:all_members_retrieve, group_id+'/member', @headers)
|
497
|
+
list_feed = Feed.new(xml_response.elements["feed"], MemberEntry)
|
498
|
+
list_feed = add_next_feeds(list_feed, xml_response, MemberEntry)
|
499
|
+
end
|
500
|
+
|
501
|
+
# Adds a owner (user or group) to a mailing list in your domain and returns a OwnerEntry instance.
|
502
|
+
# You can add addresses from other domains to your mailing list. Omit "@mydomain.com" in the group name.
|
503
|
+
# ATTENTION: a owner is added only if it's already member of the group, otherwise no action is done!
|
504
|
+
# ex :
|
505
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
506
|
+
# new_member = myapps.add_owner_to_group('example@otherdomain.com', 'mygroup')
|
507
|
+
def add_owner_to_group(email_address, group_id)
|
508
|
+
msg = RequestMessage.new
|
509
|
+
msg.about_owner(email_address)
|
510
|
+
response = request(:ownership_add, group_id+'/owner', @headers, msg.to_s)
|
511
|
+
owner_entry = OwnerEntry.new(response.elements["entry"])
|
512
|
+
end
|
513
|
+
|
514
|
+
# Removes an owner from a mailing list. Omit "@mydomain.com" in the group name.
|
515
|
+
# ATTENTION: when a owner is removed, it loses the privileges but still remains member of the group!
|
516
|
+
# ex :
|
517
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
518
|
+
# myapps.remove_owner_from_group('example@otherdomain.com', 'mygroup')
|
519
|
+
def remove_owner_from_group(email_address, group_id)
|
520
|
+
response = request(:ownership_remove, group_id+'/owner/'+email_address,@headers)
|
521
|
+
end
|
522
|
+
|
523
|
+
# Returns true if the email address (user or group) is owner of the group, false otherwise.
|
524
|
+
# ex :
|
525
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
526
|
+
# boolean = myapps.is_owner('example@otherdomain.com', 'mylist')
|
527
|
+
def is_owner(email_address, group_id)
|
528
|
+
xml_response = request(:ownership_confirm, group_id+'/owner/'+email_address, @headers)
|
529
|
+
# if the email_address is not member of the group, an error is raised, otherwise true is returned
|
530
|
+
return true
|
531
|
+
|
532
|
+
rescue GDataError => e
|
533
|
+
return false if e.reason.eql?("EntityDoesNotExist")
|
534
|
+
end
|
535
|
+
|
536
|
+
# Returns a OwnerEntry array with the owners of a group.
|
537
|
+
# ex :
|
538
|
+
# myapps = ProvisioningApi.new('root@mydomain.com','PaSsWoRd')
|
539
|
+
# list = myapps.retrieve_all_owners('mygroup')
|
540
|
+
# lists.each {|list| puts list.owner_id }
|
541
|
+
def retrieve_all_owners(group_id)
|
542
|
+
xml_response = request(:all_owners_retrieve, group_id+'/owner', @headers)
|
543
|
+
list_feed = Feed.new(xml_response.elements["feed"], OwnerEntry)
|
544
|
+
list_feed = add_next_feeds(list_feed, xml_response, OwnerEntry)
|
545
|
+
end
|
546
|
+
|
547
|
+
# Aliases
|
548
|
+
alias createUser create_user
|
549
|
+
alias retrieveUser retrieve_user
|
550
|
+
alias retrieveAllUsers retrieve_all_users
|
551
|
+
alias retrievePageOfUsers retrieve_page_of_users
|
552
|
+
alias updateUser update_user
|
553
|
+
alias renameUser rename_user
|
554
|
+
alias suspendUser suspend_user
|
555
|
+
alias restoreUser restore_user
|
556
|
+
alias deleteUser delete_user
|
557
|
+
alias createNickname create_nickname
|
558
|
+
alias retrieveNickname retrieve_nickname
|
559
|
+
alias retrieveNicknames retrieve_nicknames
|
560
|
+
alias retrieveAllNicknames retrieve_all_nicknames
|
561
|
+
alias retrievePageOfNicknames retrieve_page_of_nicknames
|
562
|
+
alias deleteNickname delete_nickname
|
563
|
+
alias retrieveAllRecipients retrieve_all_recipients
|
564
|
+
alias retrievePageOfRecipients retrieve_page_of_recipients
|
565
|
+
alias removeRecipientFromEmailList remove_address_from_email_list
|
566
|
+
alias createGroup create_group
|
567
|
+
alias updateGroup update_group
|
568
|
+
alias deleteGroup delete_group
|
569
|
+
alias retrieveGroups retrieve_groups
|
570
|
+
alias retrieveAllGroups retrieve_all_groups
|
571
|
+
alias addMemberToGroup add_member_to_group
|
572
|
+
alias removeMemberFromGroup remove_member_from_group
|
573
|
+
alias isMember is_member
|
574
|
+
alias retrieveAllMembers retrieve_all_members
|
575
|
+
alias addOwnerToGroup add_owner_to_group
|
576
|
+
alias removeOwnerFromGroup remove_owner_from_group
|
577
|
+
alias isOwner is_owner
|
578
|
+
alias retrieveAllOwners retrieve_all_owners
|
579
|
+
|
580
|
+
|
581
|
+
# private methods
|
582
|
+
private #:nodoc:
|
583
|
+
|
584
|
+
# Associates methods, http verbs and URL for REST access
|
585
|
+
def setup_actions(domain)
|
586
|
+
path_user = '/a/feeds/'+domain+'/user/2.0'
|
587
|
+
path_nickname = '/a/feeds/'+domain+'/nickname/2.0'
|
588
|
+
path_group = '/a/feeds/group/2.0/'+domain # path for Google groups
|
589
|
+
|
590
|
+
action = Hash.new
|
591
|
+
action[:domain_login] = {:method => 'POST', :path => '/accounts/ClientLogin' }
|
592
|
+
action[:user_create] = { :method => 'POST', :path => path_user }
|
593
|
+
action[:user_retrieve] = { :method => 'GET', :path => path_user+'/' }
|
594
|
+
action[:user_retrieve_all] = { :method => 'GET', :path => path_user }
|
595
|
+
action[:user_update] = { :method => 'PUT', :path => path_user +'/' }
|
596
|
+
action[:user_rename] = { :method => 'PUT', :path => path_user +'/' }
|
597
|
+
action[:user_delete] = { :method => 'DELETE', :path => path_user +'/' }
|
598
|
+
action[:nickname_create] = { :method => 'POST', :path =>path_nickname }
|
599
|
+
action[:nickname_retrieve] = { :method => 'GET', :path =>path_nickname+'/' }
|
600
|
+
action[:nickname_retrieve_all_for_user] = { :method => 'GET', :path =>path_nickname+'?username=' }
|
601
|
+
action[:nickname_retrieve_all_in_domain] = { :method => 'GET', :path =>path_nickname }
|
602
|
+
action[:nickname_delete] = { :method => 'DELETE', :path =>path_nickname+'/' }
|
603
|
+
action[:group_create] = { :method => 'POST', :path =>path_group }
|
604
|
+
action[:group_update] = { :method => 'PUT', :path =>path_group+'/' }
|
605
|
+
action[:group_delete] = { :method => 'DELETE', :path =>path_group+'/' }
|
606
|
+
action[:groups_retrieve] = { :method => 'GET', :path =>path_group+'?member=' }
|
607
|
+
action[:all_groups_retrieve] = { :method => 'GET', :path =>path_group }
|
608
|
+
action[:membership_add] = { :method => 'POST', :path =>path_group+'/' }
|
609
|
+
action[:membership_remove] = { :method => 'DELETE', :path =>path_group+'/' }
|
610
|
+
action[:membership_confirm] = { :method => 'GET', :path =>path_group+'/' }
|
611
|
+
action[:all_members_retrieve] = { :method => 'GET', :path =>path_group+'/' }
|
612
|
+
action[:ownership_add] = { :method => 'POST', :path =>path_group+'/' }
|
613
|
+
action[:ownership_remove] = { :method => 'DELETE', :path =>path_group+'/' }
|
614
|
+
action[:ownership_confirm] = { :method => 'GET', :path =>path_group+'/' }
|
615
|
+
action[:all_owners_retrieve] = { :method => 'GET', :path =>path_group+'/' }
|
616
|
+
|
617
|
+
# special action "next" for linked feed results. :path will be affected with URL received in a link tag.
|
618
|
+
action[:next] = {:method => 'GET', :path =>nil }
|
619
|
+
return action
|
620
|
+
end
|
621
|
+
|
622
|
+
# Sends credentials and returns an authentication token
|
623
|
+
def login(mail, passwd)
|
624
|
+
request_body = '&Email='+CGI.escape(mail)+'&Passwd='+CGI.escape(passwd)+'&accountType=HOSTED&service=apps'
|
625
|
+
res = request(:domain_login, nil, {'Content-Type'=>'application/x-www-form-urlencoded'}, request_body)
|
626
|
+
return /^Auth=(.+)$/.match(res.to_s)[1]
|
627
|
+
# res.to_s needed, because res.class is REXML::Document
|
628
|
+
end
|
629
|
+
|
630
|
+
|
631
|
+
# Completes the feed by following et requesting the URL links
|
632
|
+
def add_next_feeds(current_feed, xml_content, element_class)
|
633
|
+
xml_content.elements.each("feed/link") {|link|
|
634
|
+
if link.attributes["rel"] == "next"
|
635
|
+
@action[:next] = {:method => 'GET', :path=> link.attributes["href"]}
|
636
|
+
next_response = request(:next,nil,@headers)
|
637
|
+
current_feed.concat(Feed.new(next_response.elements["feed"], element_class))
|
638
|
+
current_feed = add_next_feeds(current_feed, next_response, element_class)
|
639
|
+
end
|
640
|
+
}
|
641
|
+
return current_feed
|
642
|
+
end
|
643
|
+
|
644
|
+
# Perfoms a REST request based on the action hash (cf setup_actions)
|
645
|
+
# ex : request (:user_retrieve, 'jsmith') sends a http GET www.google.com/a/feeds/domain/user/2.0/jsmith
|
646
|
+
# returns REXML Document
|
647
|
+
def request(action, value=nil, header=nil, message=nil)
|
648
|
+
#param value : value to be concatenated to action path ex: GET host/path/value
|
649
|
+
method = @action[action][:method]
|
650
|
+
value = '' if !value
|
651
|
+
path = @action[action][:path]+value
|
652
|
+
response = @connection.perform(method, path, message, header)
|
653
|
+
response_xml = Document.new(response.body)
|
654
|
+
test_errors(response_xml)
|
655
|
+
return response_xml
|
656
|
+
end
|
657
|
+
|
658
|
+
# parses xml response for an API error tag. If an error, constructs and raises a GDataError.
|
659
|
+
def test_errors(xml)
|
660
|
+
error = xml.elements["AppsForYourDomainErrors/error"]
|
661
|
+
if error
|
662
|
+
gdata_error = GDataError.new
|
663
|
+
gdata_error.code = error.attributes["errorCode"]
|
664
|
+
gdata_error.input = error.attributes["invalidInput"]
|
665
|
+
gdata_error.reason = error.attributes["reason"]
|
666
|
+
msg = "error code : "+gdata_error.code+", invalid input : "+gdata_error.input+", reason : "+gdata_error.reason
|
667
|
+
raise gdata_error, msg
|
668
|
+
end
|
669
|
+
#in case the domain is not configured to use google apps
|
670
|
+
error = xml.elements['HTML']
|
671
|
+
if(error)
|
672
|
+
gdata_error = GDataError.new
|
673
|
+
msg = /.*<TITLE>(.*)<\/TITLE>.*/.match(error.to_s)
|
674
|
+
raise gdata_error, msg[1]
|
675
|
+
end
|
676
|
+
|
677
|
+
end
|
678
|
+
end
|
679
|
+
|
680
|
+
|
681
|
+
# UserEntry object.
|
682
|
+
#
|
683
|
+
# Handles API responses relative to a user
|
684
|
+
#
|
685
|
+
# Attributes :
|
686
|
+
# username : string
|
687
|
+
# given_name : string
|
688
|
+
# family_name : string
|
689
|
+
# suspended : string "true" or string "false"
|
690
|
+
# ip_whitelisted : string "true" or string "false"
|
691
|
+
# admin : string "true" or string "false"
|
692
|
+
# change_password_at_next_login : string "true" or string "false"
|
693
|
+
# agreed_to_terms : string "true" or string "false"
|
694
|
+
# quota_limit : string (value in MB)
|
695
|
+
class UserEntry
|
696
|
+
attr_reader :given_name, :family_name, :username, :suspended, :ip_whitelisted, :admin, :change_password_at_next_login, :agreed_to_terms, :quota_limit
|
697
|
+
|
698
|
+
# UserEntry constructor. Needs a REXML::Element <entry> as parameter
|
699
|
+
def initialize(entry) #:nodoc:
|
700
|
+
@family_name = entry.elements["apps:name"].attributes["familyName"]
|
701
|
+
@given_name = entry.elements["apps:name"].attributes["givenName"]
|
702
|
+
@username = entry.elements["apps:login"].attributes["userName"]
|
703
|
+
@suspended = entry.elements["apps:login"].attributes["suspended"]
|
704
|
+
@ip_whitelisted = entry.elements["apps:login"].attributes["ipWhitelisted"]
|
705
|
+
@admin = entry.elements["apps:login"].attributes["admin"]
|
706
|
+
@change_password_at_next_login = entry.elements["apps:login"].attributes["changePasswordAtNextLogin"]
|
707
|
+
@agreed_to_terms = entry.elements["apps:login"].attributes["agreedToTerms"]
|
708
|
+
@quota_limit = entry.elements["apps:quota"].attributes["limit"]
|
709
|
+
end
|
710
|
+
end
|
711
|
+
|
712
|
+
|
713
|
+
# NicknameEntry object.
|
714
|
+
#
|
715
|
+
# Handles API responses relative to a nickname
|
716
|
+
#
|
717
|
+
# Attributes :
|
718
|
+
# login : string
|
719
|
+
# nickname : string
|
720
|
+
class NicknameEntry
|
721
|
+
attr_reader :login, :nickname
|
722
|
+
|
723
|
+
# NicknameEntry constructor. Needs a REXML::Element <entry> as parameter
|
724
|
+
def initialize(entry) #:nodoc:
|
725
|
+
@login = entry.elements["apps:login"].attributes["userName"]
|
726
|
+
@nickname = entry.elements["apps:nickname"].attributes["name"]
|
727
|
+
end
|
728
|
+
end
|
729
|
+
|
730
|
+
|
731
|
+
# UserFeed object : Array populated with Element_class objects (UserEntry, NicknameEntry, EmailListEntry or EmailListRecipientEntry)
|
732
|
+
class Feed < Array #:nodoc:
|
733
|
+
|
734
|
+
# UserFeed constructor. Populates an array with Element_class objects. Each object is an xml <entry> parsed from the REXML::Element <feed>.
|
735
|
+
# Ex : user_feed = Feed.new(xml_feed, UserEntry)
|
736
|
+
# nickname_feed = Feed.new(xml_feed, NicknameEntry)
|
737
|
+
def initialize(xml_feed, element_class)
|
738
|
+
xml_feed.elements.each("entry"){ |entry| self << element_class.new(entry) }
|
739
|
+
end
|
740
|
+
end
|
741
|
+
|
742
|
+
|
743
|
+
|
744
|
+
# GroupEntry object.
|
745
|
+
#
|
746
|
+
# Handles API responses relative to a group.
|
747
|
+
#
|
748
|
+
# Attributes :
|
749
|
+
# group_id : string . The group_id is written without "@" and everything following.
|
750
|
+
class GroupEntry
|
751
|
+
attr_reader :group_id
|
752
|
+
|
753
|
+
# GroupEntry constructor. Needs a REXML::Element <entry> as parameter
|
754
|
+
def initialize(entry) #:nodoc:
|
755
|
+
entry.elements.each("apps:property"){ |e| @group_id = e.attributes["value"] if e.attributes["name"].eql?("groupId") }
|
756
|
+
end
|
757
|
+
end
|
758
|
+
|
759
|
+
|
760
|
+
# MemberEntry object.
|
761
|
+
#
|
762
|
+
# Handles API responses relative to a meber of a group.
|
763
|
+
#
|
764
|
+
# Attributes :
|
765
|
+
# member_id : string . The member_id is a complete email address.
|
766
|
+
class MemberEntry
|
767
|
+
attr_reader :member_id
|
768
|
+
|
769
|
+
# MemberEntry constructor. Needs a REXML::Element <entry> as parameter
|
770
|
+
def initialize(entry) #:nodoc:
|
771
|
+
entry.elements.each("apps:property"){ |e| @member_id = e.attributes["value"] if e.attributes["name"].eql?("memberId") }
|
772
|
+
end
|
773
|
+
end
|
774
|
+
|
775
|
+
|
776
|
+
# OwnerEntry object.
|
777
|
+
#
|
778
|
+
# Handles API responses relative to a owner of a group.
|
779
|
+
#
|
780
|
+
# Attributes :
|
781
|
+
# owner_id : string . The owner_id is a complete email address.
|
782
|
+
class OwnerEntry
|
783
|
+
attr_reader :owner_id
|
784
|
+
|
785
|
+
# OwnerEntry constructor. Needs a REXML::Element <entry> as parameter
|
786
|
+
def initialize(entry) #:nodoc:
|
787
|
+
entry.elements.each("apps:property"){ |e| @owner_id = e.attributes["value"] if e.attributes["name"].eql?("email") }
|
788
|
+
end
|
789
|
+
end
|
790
|
+
|
791
|
+
|
792
|
+
class RequestMessage < Document #:nodoc:
|
793
|
+
# Request message constructor.
|
794
|
+
# parameter type : "user", "nickname" or "emailList"
|
795
|
+
|
796
|
+
# creates the object and initiates the construction
|
797
|
+
def initialize
|
798
|
+
super '<?xml version="1.0" encoding="UTF-8"?>'
|
799
|
+
self.add_element "atom:entry", {"xmlns:apps" => "http://schemas.google.com/apps/2006",
|
800
|
+
"xmlns:gd" => "http://schemas.google.com/g/2005",
|
801
|
+
"xmlns:atom" => "http://www.w3.org/2005/Atom"}
|
802
|
+
self.elements["atom:entry"].add_element "atom:category", {"scheme" => "http://schemas.google.com/g/2005#kind"}
|
803
|
+
end
|
804
|
+
|
805
|
+
# adds <atom:id> element in the message body. Url is inserted as a text.
|
806
|
+
def add_path(url)
|
807
|
+
self.elements["atom:entry"].add_element "atom:id"
|
808
|
+
self.elements["atom:entry/atom:id"].text = url
|
809
|
+
end
|
810
|
+
|
811
|
+
# adds <apps:emailList> element in the message body.
|
812
|
+
def about_email_list(email_list)
|
813
|
+
self.elements["atom:entry/atom:category"].add_attribute("term", "http://schemas.google.com/apps/2006#emailList")
|
814
|
+
self.elements["atom:entry"].add_element "apps:emailList", {"name" => email_list }
|
815
|
+
end
|
816
|
+
|
817
|
+
# adds <apps:property> element in the message body for a group.
|
818
|
+
def about_group(group_id, properties)
|
819
|
+
self.elements["atom:entry/atom:category"].add_attribute("term", "http://schemas.google.com/apps/2006#emailList")
|
820
|
+
self.elements["atom:entry"].add_element "apps:property", {"name" => "groupId", "value" => group_id }
|
821
|
+
self.elements["atom:entry"].add_element "apps:property", {"name" => "groupName", "value" => properties[0] }
|
822
|
+
self.elements["atom:entry"].add_element "apps:property", {"name" => "description", "value" => properties[1] }
|
823
|
+
self.elements["atom:entry"].add_element "apps:property", {"name" => "emailPermission", "value" => properties[2] }
|
824
|
+
end
|
825
|
+
|
826
|
+
# adds <apps:property> element in the message body for a member.
|
827
|
+
def about_member(email_address)
|
828
|
+
self.elements["atom:entry/atom:category"].add_attribute("term", "http://schemas.google.com/apps/2006#user")
|
829
|
+
self.elements["atom:entry"].add_element "apps:property", {"name" => "memberId", "value" => email_address }
|
830
|
+
end
|
831
|
+
|
832
|
+
# adds <apps:property> element in the message body for an owner.
|
833
|
+
def about_owner(email_address)
|
834
|
+
self.elements["atom:entry/atom:category"].add_attribute("term", "http://schemas.google.com/apps/2006#user")
|
835
|
+
self.elements["atom:entry"].add_element "apps:property", {"name" => "email", "value" => email_address }
|
836
|
+
end
|
837
|
+
|
838
|
+
|
839
|
+
# adds <apps:login> element in the message body.
|
840
|
+
# warning : if valued admin, suspended, or change_passwd_at_next_login must be the STRINGS "true" or "false", not the boolean true or false
|
841
|
+
# when needed to construct the message, should always been used before other "about_" methods so that the category tag can be overwritten
|
842
|
+
# only values permitted for hash_function_function_name : "SHA-1", "MD5" or nil
|
843
|
+
def about_login(user_name, passwd=nil, hash_function_name=nil, admin=nil, suspended=nil, change_passwd_at_next_login=nil)
|
844
|
+
self.elements["atom:entry/atom:category"].add_attribute("term", "http://schemas.google.com/apps/2006#user")
|
845
|
+
self.elements["atom:entry"].add_element "apps:login", {"userName" => user_name }
|
846
|
+
self.elements["atom:entry/apps:login"].add_attribute("password", passwd) if not passwd.nil?
|
847
|
+
self.elements["atom:entry/apps:login"].add_attribute("hashFunctionName", hash_function_name) if not hash_function_name.nil?
|
848
|
+
self.elements["atom:entry/apps:login"].add_attribute("admin", admin) if not admin.nil?
|
849
|
+
self.elements["atom:entry/apps:login"].add_attribute("suspended", suspended) if not suspended.nil?
|
850
|
+
self.elements["atom:entry/apps:login"].add_attribute("changePasswordAtNextLogin", change_passwd_at_next_login) if not change_passwd_at_next_login.nil?
|
851
|
+
return self
|
852
|
+
end
|
853
|
+
|
854
|
+
# adds <apps:quota> in the message body.
|
855
|
+
# limit in MB: integer
|
856
|
+
def about_quota(limit)
|
857
|
+
self.elements["atom:entry"].add_element "apps:quota", {"limit" => limit }
|
858
|
+
return self
|
859
|
+
end
|
860
|
+
|
861
|
+
# adds <apps:name> in the message body.
|
862
|
+
def about_name(family_name, given_name)
|
863
|
+
self.elements["atom:entry"].add_element "apps:name", {"familyName" => family_name, "givenName" => given_name }
|
864
|
+
return self
|
865
|
+
end
|
866
|
+
|
867
|
+
# adds <apps:nickname> in the message body.
|
868
|
+
def about_nickname(name)
|
869
|
+
self.elements["atom:entry/atom:category"].add_attribute("term", "http://schemas.google.com/apps/2006#nickname")
|
870
|
+
self.elements["atom:entry"].add_element "apps:nickname", {"name" => name}
|
871
|
+
return self
|
872
|
+
end
|
873
|
+
|
874
|
+
# adds <gd:who> in the message body.
|
875
|
+
def about_who(email)
|
876
|
+
self.elements["atom:entry"].add_element "gd:who", {"email" => email }
|
877
|
+
return self
|
878
|
+
end
|
879
|
+
|
880
|
+
end
|
881
|
+
|
882
|
+
end
|