PageRenderTime 53ms CodeModel.GetById 14ms app.highlight 34ms RepoModel.GetById 1ms app.codeStats 0ms

/gdata/apps/service.py

http://radioappz.googlecode.com/
Python | 550 lines | 515 code | 14 blank | 21 comment | 0 complexity | 44c79070a2e7cecbf9a377824f72b161 MD5 | raw file
  1#!/usr/bin/python
  2#
  3# Copyright (C) 2007 SIOS Technology, Inc.
  4#
  5# Licensed under the Apache License, Version 2.0 (the "License");
  6# you may not use this file except in compliance with the License.
  7# You may obtain a copy of the License at
  8#
  9#      http://www.apache.org/licenses/LICENSE-2.0
 10#
 11# Unless required by applicable law or agreed to in writing, software
 12# distributed under the License is distributed on an "AS IS" BASIS,
 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14# See the License for the specific language governing permissions and
 15# limitations under the License.
 16
 17__author__ = 'tmatsuo@sios.com (Takashi MATSUO)'
 18
 19try:
 20  from xml.etree import cElementTree as ElementTree
 21except ImportError:
 22  try:
 23    import cElementTree as ElementTree
 24  except ImportError:
 25    try:
 26      from xml.etree import ElementTree
 27    except ImportError:
 28      from elementtree import ElementTree
 29import urllib
 30import gdata
 31import atom.service
 32import gdata.service
 33import gdata.apps
 34import atom
 35
 36API_VER="2.0"
 37HTTP_OK=200
 38
 39UNKOWN_ERROR=1000
 40USER_DELETED_RECENTLY=1100
 41USER_SUSPENDED=1101
 42DOMAIN_USER_LIMIT_EXCEEDED=1200
 43DOMAIN_ALIAS_LIMIT_EXCEEDED=1201
 44DOMAIN_SUSPENDED=1202
 45DOMAIN_FEATURE_UNAVAILABLE=1203
 46ENTITY_EXISTS=1300
 47ENTITY_DOES_NOT_EXIST=1301
 48ENTITY_NAME_IS_RESERVED=1302
 49ENTITY_NAME_NOT_VALID=1303
 50INVALID_GIVEN_NAME=1400
 51INVALID_FAMILY_NAME=1401
 52INVALID_PASSWORD=1402
 53INVALID_USERNAME=1403
 54INVALID_HASH_FUNCTION_NAME=1404
 55INVALID_HASH_DIGGEST_LENGTH=1405
 56INVALID_EMAIL_ADDRESS=1406
 57INVALID_QUERY_PARAMETER_VALUE=1407
 58TOO_MANY_RECIPIENTS_ON_EMAIL_LIST=1500
 59
 60DEFAULT_QUOTA_LIMIT='2048'
 61
 62
 63class Error(Exception):
 64  pass
 65
 66
 67class AppsForYourDomainException(Error):
 68
 69  def __init__(self, response):
 70
 71    Error.__init__(self, response)
 72    try:
 73      self.element_tree = ElementTree.fromstring(response['body'])
 74      self.error_code = int(self.element_tree[0].attrib['errorCode'])
 75      self.reason = self.element_tree[0].attrib['reason']
 76      self.invalidInput = self.element_tree[0].attrib['invalidInput']
 77    except:
 78      self.error_code = UNKOWN_ERROR
 79
 80
 81class AppsService(gdata.service.GDataService):
 82  """Client for the Google Apps Provisioning service."""
 83
 84  def __init__(self, email=None, password=None, domain=None, source=None,
 85               server='apps-apis.google.com', additional_headers=None,
 86               **kwargs):
 87    """Creates a client for the Google Apps Provisioning service.
 88
 89    Args:
 90      email: string (optional) The user's email address, used for
 91          authentication.
 92      password: string (optional) The user's password.
 93      domain: string (optional) The Google Apps domain name.
 94      source: string (optional) The name of the user's application.
 95      server: string (optional) The name of the server to which a connection
 96          will be opened. Default value: 'apps-apis.google.com'.
 97      **kwargs: The other parameters to pass to gdata.service.GDataService
 98          constructor.
 99    """
100    gdata.service.GDataService.__init__(
101        self, email=email, password=password, service='apps', source=source,
102        server=server, additional_headers=additional_headers, **kwargs)
103    self.ssl = True
104    self.port = 443
105    self.domain = domain
106
107  def _baseURL(self):
108    return "/a/feeds/%s" % self.domain 
109
110  def AddAllElementsFromAllPages(self, link_finder, func):
111    """retrieve all pages and add all elements"""
112    next = link_finder.GetNextLink()
113    while next is not None:
114      next_feed = self.Get(next.href, converter=func)
115      for a_entry in next_feed.entry:
116        link_finder.entry.append(a_entry)
117      next = next_feed.GetNextLink()
118    return link_finder
119
120  def RetrievePageOfEmailLists(self, start_email_list_name=None,
121                               num_retries=gdata.service.DEFAULT_NUM_RETRIES,
122                               delay=gdata.service.DEFAULT_DELAY,
123                               backoff=gdata.service.DEFAULT_BACKOFF):
124    """Retrieve one page of email list"""
125    uri = "%s/emailList/%s" % (self._baseURL(), API_VER)
126    if start_email_list_name is not None:
127      uri += "?startEmailListName=%s" % start_email_list_name
128    try:
129      return gdata.apps.EmailListFeedFromString(str(self.GetWithRetries(
130            uri, num_retries=num_retries, delay=delay, backoff=backoff)))
131    except gdata.service.RequestError, e:
132      raise AppsForYourDomainException(e.args[0])
133    
134  def GetGeneratorForAllEmailLists(
135    self, num_retries=gdata.service.DEFAULT_NUM_RETRIES,
136    delay=gdata.service.DEFAULT_DELAY, backoff=gdata.service.DEFAULT_BACKOFF):
137    """Retrieve a generator for all emaillists in this domain."""
138    first_page = self.RetrievePageOfEmailLists(num_retries=num_retries,
139                                               delay=delay,
140                                               backoff=backoff)
141    return self.GetGeneratorFromLinkFinder(
142      first_page, gdata.apps.EmailListRecipientFeedFromString,
143      num_retries=num_retries, delay=delay, backoff=backoff)
144
145  def RetrieveAllEmailLists(self):
146    """Retrieve all email list of a domain."""
147
148    ret = self.RetrievePageOfEmailLists()
149    # pagination
150    return self.AddAllElementsFromAllPages(
151      ret, gdata.apps.EmailListFeedFromString)
152
153  def RetrieveEmailList(self, list_name):
154    """Retreive a single email list by the list's name."""
155
156    uri = "%s/emailList/%s/%s" % (
157      self._baseURL(), API_VER, list_name)
158    try:
159      return self.Get(uri, converter=gdata.apps.EmailListEntryFromString)
160    except gdata.service.RequestError, e:
161      raise AppsForYourDomainException(e.args[0])
162
163  def RetrieveEmailLists(self, recipient):
164    """Retrieve All Email List Subscriptions for an Email Address."""
165
166    uri = "%s/emailList/%s?recipient=%s" % (
167      self._baseURL(), API_VER, recipient)
168    try:
169      ret = gdata.apps.EmailListFeedFromString(str(self.Get(uri)))
170    except gdata.service.RequestError, e:
171      raise AppsForYourDomainException(e.args[0])
172    
173    # pagination
174    return self.AddAllElementsFromAllPages(
175      ret, gdata.apps.EmailListFeedFromString)
176
177  def RemoveRecipientFromEmailList(self, recipient, list_name):
178    """Remove recipient from email list."""
179    
180    uri = "%s/emailList/%s/%s/recipient/%s" % (
181      self._baseURL(), API_VER, list_name, recipient)
182    try:
183      self.Delete(uri)
184    except gdata.service.RequestError, e:
185      raise AppsForYourDomainException(e.args[0])
186
187  def RetrievePageOfRecipients(self, list_name, start_recipient=None,
188                               num_retries=gdata.service.DEFAULT_NUM_RETRIES,
189                               delay=gdata.service.DEFAULT_DELAY,
190                               backoff=gdata.service.DEFAULT_BACKOFF):
191    """Retrieve one page of recipient of an email list. """
192
193    uri = "%s/emailList/%s/%s/recipient" % (
194      self._baseURL(), API_VER, list_name)
195
196    if start_recipient is not None:
197      uri += "?startRecipient=%s" % start_recipient
198    try:
199      return gdata.apps.EmailListRecipientFeedFromString(str(
200          self.GetWithRetries(
201            uri, num_retries=num_retries, delay=delay, backoff=backoff)))
202    except gdata.service.RequestError, e:
203      raise AppsForYourDomainException(e.args[0])
204
205  def GetGeneratorForAllRecipients(
206    self, list_name, num_retries=gdata.service.DEFAULT_NUM_RETRIES,
207    delay=gdata.service.DEFAULT_DELAY, backoff=gdata.service.DEFAULT_BACKOFF):
208    """Retrieve a generator for all recipients of a particular emaillist."""
209    first_page = self.RetrievePageOfRecipients(list_name,
210                                               num_retries=num_retries,
211                                               delay=delay,
212                                               backoff=backoff)
213    return self.GetGeneratorFromLinkFinder(
214      first_page, gdata.apps.EmailListRecipientFeedFromString,
215      num_retries=num_retries, delay=delay, backoff=backoff)
216
217  def RetrieveAllRecipients(self, list_name):
218    """Retrieve all recipient of an email list."""
219
220    ret = self.RetrievePageOfRecipients(list_name)
221    # pagination
222    return self.AddAllElementsFromAllPages(
223      ret, gdata.apps.EmailListRecipientFeedFromString)
224
225  def AddRecipientToEmailList(self, recipient, list_name):
226    """Add a recipient to a email list."""
227
228    uri = "%s/emailList/%s/%s/recipient" % (
229      self._baseURL(), API_VER, list_name)
230    recipient_entry = gdata.apps.EmailListRecipientEntry()
231    recipient_entry.who = gdata.apps.Who(email=recipient)
232
233    try:
234      return gdata.apps.EmailListRecipientEntryFromString(
235        str(self.Post(recipient_entry, uri)))
236    except gdata.service.RequestError, e:
237      raise AppsForYourDomainException(e.args[0])
238
239  def DeleteEmailList(self, list_name):
240    """Delete a email list"""
241
242    uri = "%s/emailList/%s/%s" % (self._baseURL(), API_VER, list_name)
243    try:
244      self.Delete(uri)
245    except gdata.service.RequestError, e:
246      raise AppsForYourDomainException(e.args[0])
247
248  def CreateEmailList(self, list_name):
249    """Create a email list. """
250
251    uri = "%s/emailList/%s" % (self._baseURL(), API_VER)
252    email_list_entry = gdata.apps.EmailListEntry()
253    email_list_entry.email_list = gdata.apps.EmailList(name=list_name)
254    try: 
255      return gdata.apps.EmailListEntryFromString(
256        str(self.Post(email_list_entry, uri)))
257    except gdata.service.RequestError, e:
258      raise AppsForYourDomainException(e.args[0])
259
260  def DeleteNickname(self, nickname):
261    """Delete a nickname"""
262
263    uri = "%s/nickname/%s/%s" % (self._baseURL(), API_VER, nickname)
264    try:
265      self.Delete(uri)
266    except gdata.service.RequestError, e:
267      raise AppsForYourDomainException(e.args[0])
268
269  def RetrievePageOfNicknames(self, start_nickname=None,
270                              num_retries=gdata.service.DEFAULT_NUM_RETRIES,
271                              delay=gdata.service.DEFAULT_DELAY,
272                              backoff=gdata.service.DEFAULT_BACKOFF):
273    """Retrieve one page of nicknames in the domain"""
274
275    uri = "%s/nickname/%s" % (self._baseURL(), API_VER)
276    if start_nickname is not None:
277      uri += "?startNickname=%s" % start_nickname
278    try:
279      return gdata.apps.NicknameFeedFromString(str(self.GetWithRetries(
280            uri, num_retries=num_retries, delay=delay, backoff=backoff)))
281    except gdata.service.RequestError, e:
282      raise AppsForYourDomainException(e.args[0])
283
284  def GetGeneratorForAllNicknames(
285    self, num_retries=gdata.service.DEFAULT_NUM_RETRIES,
286    delay=gdata.service.DEFAULT_DELAY, backoff=gdata.service.DEFAULT_BACKOFF):
287    """Retrieve a generator for all nicknames in this domain."""
288    first_page = self.RetrievePageOfNicknames(num_retries=num_retries,
289                                              delay=delay,
290                                              backoff=backoff)
291    return self.GetGeneratorFromLinkFinder(
292      first_page, gdata.apps.NicknameFeedFromString, num_retries=num_retries,
293      delay=delay, backoff=backoff)
294
295  def RetrieveAllNicknames(self):
296    """Retrieve all nicknames in the domain"""
297
298    ret = self.RetrievePageOfNicknames()
299    # pagination
300    return self.AddAllElementsFromAllPages(
301      ret, gdata.apps.NicknameFeedFromString)
302
303  def GetGeneratorForAllNicknamesOfAUser(
304    self, user_name, num_retries=gdata.service.DEFAULT_NUM_RETRIES,
305    delay=gdata.service.DEFAULT_DELAY, backoff=gdata.service.DEFAULT_BACKOFF):
306    """Retrieve a generator for all nicknames of a particular user."""
307    uri = "%s/nickname/%s?username=%s" % (self._baseURL(), API_VER, user_name)
308    try:
309      first_page = gdata.apps.NicknameFeedFromString(str(self.GetWithRetries(
310            uri, num_retries=num_retries, delay=delay, backoff=backoff)))
311    except gdata.service.RequestError, e:
312      raise AppsForYourDomainException(e.args[0])
313    return self.GetGeneratorFromLinkFinder(
314      first_page, gdata.apps.NicknameFeedFromString, num_retries=num_retries,
315      delay=delay, backoff=backoff)
316
317  def RetrieveNicknames(self, user_name):
318    """Retrieve nicknames of the user"""
319
320    uri = "%s/nickname/%s?username=%s" % (self._baseURL(), API_VER, user_name)
321    try:
322      ret = gdata.apps.NicknameFeedFromString(str(self.Get(uri)))
323    except gdata.service.RequestError, e:
324      raise AppsForYourDomainException(e.args[0])
325
326    # pagination
327    return self.AddAllElementsFromAllPages(
328      ret, gdata.apps.NicknameFeedFromString)
329
330  def RetrieveNickname(self, nickname):
331    """Retrieve a nickname.
332
333    Args:
334      nickname: string The nickname to retrieve
335
336    Returns:
337      gdata.apps.NicknameEntry
338    """
339
340    uri = "%s/nickname/%s/%s" % (self._baseURL(), API_VER, nickname)
341    try:
342      return gdata.apps.NicknameEntryFromString(str(self.Get(uri)))
343    except gdata.service.RequestError, e:
344      raise AppsForYourDomainException(e.args[0])
345
346  def CreateNickname(self, user_name, nickname):
347    """Create a nickname"""
348
349    uri = "%s/nickname/%s" % (self._baseURL(), API_VER)
350    nickname_entry = gdata.apps.NicknameEntry()
351    nickname_entry.login = gdata.apps.Login(user_name=user_name)
352    nickname_entry.nickname = gdata.apps.Nickname(name=nickname)
353
354    try: 
355      return gdata.apps.NicknameEntryFromString(
356        str(self.Post(nickname_entry, uri)))
357    except gdata.service.RequestError, e:
358      raise AppsForYourDomainException(e.args[0])
359
360  def DeleteUser(self, user_name):
361    """Delete a user account"""
362
363    uri = "%s/user/%s/%s" % (self._baseURL(), API_VER, user_name)
364    try:
365      return self.Delete(uri)
366    except gdata.service.RequestError, e:
367      raise AppsForYourDomainException(e.args[0])
368
369  def UpdateUser(self, user_name, user_entry):
370    """Update a user account."""
371
372    uri = "%s/user/%s/%s" % (self._baseURL(), API_VER, user_name)
373    try: 
374      return gdata.apps.UserEntryFromString(str(self.Put(user_entry, uri)))
375    except gdata.service.RequestError, e:
376      raise AppsForYourDomainException(e.args[0])
377
378  def CreateUser(self, user_name, family_name, given_name, password,
379                 suspended='false', quota_limit=None, 
380                 password_hash_function=None):
381    """Create a user account. """
382
383    uri = "%s/user/%s" % (self._baseURL(), API_VER)
384    user_entry = gdata.apps.UserEntry()
385    user_entry.login = gdata.apps.Login(
386        user_name=user_name, password=password, suspended=suspended,
387        hash_function_name=password_hash_function)
388    user_entry.name = gdata.apps.Name(family_name=family_name,
389                                      given_name=given_name)
390    if quota_limit is not None:
391      user_entry.quota = gdata.apps.Quota(limit=str(quota_limit))
392
393    try: 
394      return gdata.apps.UserEntryFromString(str(self.Post(user_entry, uri)))
395    except gdata.service.RequestError, e:
396      raise AppsForYourDomainException(e.args[0])
397
398  def SuspendUser(self, user_name):
399    user_entry = self.RetrieveUser(user_name)
400    if user_entry.login.suspended != 'true':
401      user_entry.login.suspended = 'true'
402      user_entry = self.UpdateUser(user_name, user_entry)
403    return user_entry
404
405  def RestoreUser(self, user_name):
406    user_entry = self.RetrieveUser(user_name)
407    if user_entry.login.suspended != 'false':
408      user_entry.login.suspended = 'false'
409      user_entry = self.UpdateUser(user_name, user_entry)
410    return user_entry
411
412  def RetrieveUser(self, user_name):
413    """Retrieve an user account.
414
415    Args:
416      user_name: string The user name to retrieve
417
418    Returns:
419      gdata.apps.UserEntry
420    """
421
422    uri = "%s/user/%s/%s" % (self._baseURL(), API_VER, user_name)
423    try:
424      return gdata.apps.UserEntryFromString(str(self.Get(uri)))
425    except gdata.service.RequestError, e:
426      raise AppsForYourDomainException(e.args[0])
427
428  def RetrievePageOfUsers(self, start_username=None,
429                          num_retries=gdata.service.DEFAULT_NUM_RETRIES,
430                          delay=gdata.service.DEFAULT_DELAY,
431                          backoff=gdata.service.DEFAULT_BACKOFF):
432    """Retrieve one page of users in this domain."""
433
434    uri = "%s/user/%s" % (self._baseURL(), API_VER)
435    if start_username is not None:
436      uri += "?startUsername=%s" % start_username
437    try:
438      return gdata.apps.UserFeedFromString(str(self.GetWithRetries(
439          uri, num_retries=num_retries, delay=delay, backoff=backoff)))
440    except gdata.service.RequestError, e:
441      raise AppsForYourDomainException(e.args[0])
442
443  def GetGeneratorForAllUsers(self,
444                              num_retries=gdata.service.DEFAULT_NUM_RETRIES,
445                              delay=gdata.service.DEFAULT_DELAY,
446                              backoff=gdata.service.DEFAULT_BACKOFF):
447    """Retrieve a generator for all users in this domain."""
448    first_page = self.RetrievePageOfUsers(num_retries=num_retries, delay=delay,
449                                          backoff=backoff)
450    return self.GetGeneratorFromLinkFinder(
451      first_page, gdata.apps.UserFeedFromString, num_retries=num_retries,
452      delay=delay, backoff=backoff)
453
454  def RetrieveAllUsers(self):
455    """Retrieve all users in this domain. OBSOLETE"""
456
457    ret = self.RetrievePageOfUsers()
458    # pagination
459    return self.AddAllElementsFromAllPages(
460      ret, gdata.apps.UserFeedFromString)
461
462
463class PropertyService(gdata.service.GDataService):
464  """Client for the Google Apps Property service."""
465
466  def __init__(self, email=None, password=None, domain=None, source=None,
467               server='apps-apis.google.com', additional_headers=None):
468    gdata.service.GDataService.__init__(self, email=email, password=password,
469                                        service='apps', source=source,
470                                        server=server,
471                                        additional_headers=additional_headers)
472    self.ssl = True
473    self.port = 443
474    self.domain = domain
475
476  def AddAllElementsFromAllPages(self, link_finder, func):
477    """retrieve all pages and add all elements"""
478    next = link_finder.GetNextLink()
479    while next is not None:
480      next_feed = self.Get(next.href, converter=func)
481      for a_entry in next_feed.entry:
482        link_finder.entry.append(a_entry)
483      next = next_feed.GetNextLink()
484    return link_finder
485
486  def _GetPropertyEntry(self, properties):
487    property_entry = gdata.apps.PropertyEntry()
488    property = []
489    for name, value in properties.iteritems():
490      if name is not None and value is not None:
491        property.append(gdata.apps.Property(name=name, value=value))
492    property_entry.property = property
493    return property_entry
494
495  def _PropertyEntry2Dict(self, property_entry):
496    properties = {}
497    for i, property in enumerate(property_entry.property):
498      properties[property.name] = property.value
499    return properties
500
501  def _GetPropertyFeed(self, uri):
502    try:
503      return gdata.apps.PropertyFeedFromString(str(self.Get(uri)))
504    except gdata.service.RequestError, e:
505      raise gdata.apps.service.AppsForYourDomainException(e.args[0])
506
507  def _GetPropertiesList(self, uri):
508    property_feed = self._GetPropertyFeed(uri)
509    # pagination
510    property_feed = self.AddAllElementsFromAllPages(
511      property_feed, gdata.apps.PropertyFeedFromString)
512    properties_list = []
513    for property_entry in property_feed.entry:
514      properties_list.append(self._PropertyEntry2Dict(property_entry))
515    return properties_list
516
517  def _GetProperties(self, uri):
518    try:
519      return self._PropertyEntry2Dict(gdata.apps.PropertyEntryFromString(
520        str(self.Get(uri))))
521    except gdata.service.RequestError, e:
522      raise gdata.apps.service.AppsForYourDomainException(e.args[0])
523
524  def _PostProperties(self, uri, properties):
525    property_entry = self._GetPropertyEntry(properties)
526    try:
527      return self._PropertyEntry2Dict(gdata.apps.PropertyEntryFromString(
528        str(self.Post(property_entry, uri))))
529    except gdata.service.RequestError, e:
530      raise gdata.apps.service.AppsForYourDomainException(e.args[0])
531
532  def _PutProperties(self, uri, properties):
533    property_entry = self._GetPropertyEntry(properties)
534    try:
535      return self._PropertyEntry2Dict(gdata.apps.PropertyEntryFromString(
536        str(self.Put(property_entry, uri))))
537    except gdata.service.RequestError, e:
538      raise gdata.apps.service.AppsForYourDomainException(e.args[0])
539
540  def _DeleteProperties(self, uri):
541    try:
542      self.Delete(uri)
543    except gdata.service.RequestError, e:
544      raise gdata.apps.service.AppsForYourDomainException(e.args[0])
545
546
547def _bool2str(b):
548  if b is None:
549    return None
550  return str(b is True).lower()