#!/usr/bin/env python
# Copyright (C) 2008 Google, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Allow Google Apps domain administrators to audit user data.

  AuditService: Set auditing."""

__author__ = 'jlee@pbu.edu'

from base64 import b64encode

import gdata.apps
import gdata.apps.service
import gdata.service

class AuditService(gdata.apps.service.PropertyService):
  """Client for the Google Apps Audit service."""

  def _serviceUrl(self, setting_id, domain=None, user=None):
    if domain is None:
      domain = self.domain
    if user is None:
      return '/a/feeds/compliance/audit/%s/%s' % (setting_id, domain)
    else:
      return '/a/feeds/compliance/audit/%s/%s/%s' % (setting_id, domain, user)

  def updatePGPKey(self, pgpkey):
    """Updates Public PGP Key Google uses to encrypt audit data

    Args:
      pgpkey: string, ASCII text of PGP Public Key to be used

    Returns:
      A dict containing the result of the POST operation."""

    uri = self._serviceUrl('publickey')
    b64pgpkey = b64encode(pgpkey)
    properties = {}
    properties['publicKey'] = b64pgpkey
    return self._PostProperties(uri, properties)

  def createEmailMonitor(self, source_user, destination_user, end_date, 
                         begin_date=None, incoming_headers_only=False, 
                         outgoing_headers_only=False, drafts=False, 
                         drafts_headers_only=False, chats=False, 
                         chats_headers_only=False):
    """Creates a email monitor, forwarding the source_users emails/chats

    Args:
      source_user: string, the user whose email will be audited
      destination_user: string, the user to receive the audited email
      end_date: string, the date the audit will end in
                "yyyy-MM-dd HH:mm" format, required
      begin_date: string, the date the audit will start in 
                  "yyyy-MM-dd HH:mm" format, leave blank to use current time
      incoming_headers_only: boolean, whether to audit only the headers of
                             mail delivered to source user
      outgoing_headers_only: boolean, whether to audit only the headers of
                             mail sent from the source user
      drafts: boolean, whether to audit draft messages of the source user
      drafts_headers_only: boolean, whether to audit only the headers of
                           mail drafts saved by the user
      chats: boolean, whether to audit archived chats of the source user
      chats_headers_only: boolean, whether to audit only the headers of
                          archived chats of the source user

    Returns:
      A dict containing the result of the POST operation."""

    uri = self._serviceUrl('mail/monitor', user=source_user)
    properties = {}
    properties['destUserName'] = destination_user
    if begin_date is not None:
      properties['beginDate'] = begin_date
    properties['endDate'] = end_date
    if incoming_headers_only:
      properties['incomingEmailMonitorLevel'] = 'HEADER_ONLY'
    else:
      properties['incomingEmailMonitorLevel'] = 'FULL_MESSAGE'
    if outgoing_headers_only:
      properties['outgoingEmailMonitorLevel'] = 'HEADER_ONLY'
    else:
      properties['outgoingEmailMonitorLevel'] = 'FULL_MESSAGE'
    if drafts:
      if drafts_headers_only:
        properties['draftMonitorLevel'] = 'HEADER_ONLY'
      else:
        properties['draftMonitorLevel'] = 'FULL_MESSAGE'
    if chats:
      if chats_headers_only:
        properties['chatMonitorLevel'] = 'HEADER_ONLY'
      else:
        properties['chatMonitorLevel'] = 'FULL_MESSAGE'
    return self._PostProperties(uri, properties)

  def getEmailMonitors(self, user):
    """"Gets the email monitors for the given user

    Args:
      user: string, the user to retrieve email monitors for

    Returns:
      list results of the POST operation

    """
    uri = self._serviceUrl('mail/monitor', user=user)
    return self._GetPropertiesList(uri)

  def deleteEmailMonitor(self, source_user, destination_user):
    """Deletes the email monitor for the given user

    Args:
      source_user: string, the user who is being monitored
      destination_user: string, theuser who recieves the monitored emails

    Returns:
      Nothing
    """

    uri = self._serviceUrl('mail/monitor', user=source_user+'/'+destination_user)
    try:
      return self._DeleteProperties(uri)
    except gdata.service.RequestError as e:
      raise gdata.apps.service.AppsForYourDomainException(e.args[0])

  def createAccountInformationRequest(self, user):
    """Creates a request for account auditing details

    Args:
      user: string, the user to request account information for

    Returns:
      A dict containing the result of the post operation."""

    uri = self._serviceUrl('account', user=user)
    properties = {}
    #XML Body is left empty
    try:
      return self._PostProperties(uri, properties)
    except gdata.service.RequestError as e:
      raise gdata.apps.service.AppsForYourDomainException(e.args[0])

  def getAccountInformationRequestStatus(self, user, request_id):
    """Gets the status of an account auditing request

    Args:
      user: string, the user whose account auditing details were requested
      request_id: string, the request_id

    Returns:
      A dict containing the result of the get operation."""

    uri = self._serviceUrl('account', user=user+'/'+request_id)
    try:
      return self._GetProperties(uri)
    except gdata.service.RequestError as e:
      raise gdata.apps.service.AppsForYourDomainException(e.args[0])

  def getAllAccountInformationRequestsStatus(self):
    """Gets the status of all account auditing requests for the domain

    Args:
      None

    Returns:
      list results of the POST operation
    """

    uri = self._serviceUrl('account')
    return self._GetPropertiesList(uri)


  def deleteAccountInformationRequest(self, user, request_id):
    """Deletes the request for account auditing information

   Args:
     user: string, the user whose account auditing details were requested
     request_id: string, the request_id

   Returns:
     Nothing
   """

    uri = self._serviceUrl('account', user=user+'/'+request_id)
    try:
      return self._DeleteProperties(uri)
    except gdata.service.RequestError as e:
      raise gdata.apps.service.AppsForYourDomainException(e.args[0])

  def createMailboxExportRequest(self, user, begin_date=None, end_date=None, include_deleted=False, search_query=None, headers_only=False):
    """Creates a mailbox export request

    Args:
      user: string, the user whose mailbox export is being requested
      begin_date: string, date of earliest emails to export, optional, defaults to date of account creation
                  format is 'yyyy-MM-dd HH:mm'
      end_date: string, date of latest emails to export, optional, defaults to current date
                format is 'yyyy-MM-dd HH:mm'
      include_deleted: boolean, whether to include deleted emails in export, mutually exclusive with search_query
      search_query: string, gmail style search query, matched emails will be exported, mutually exclusive with include_deleted

    Returns:
      A dict containing the result of the post operation."""

    uri = self._serviceUrl('mail/export', user=user)
    properties = {}
    if begin_date is not None:
      properties['beginDate'] = begin_date
    if end_date is not None:
      properties['endDate'] = end_date
    if include_deleted is not None:
      properties['includeDeleted'] = gdata.apps.service._bool2str(include_deleted)
    if search_query is not None:
      properties['searchQuery'] = search_query
    if headers_only is True:
      properties['packageContent'] = 'HEADER_ONLY'
    else:
      properties['packageContent'] = 'FULL_MESSAGE'
    return self._PostProperties(uri, properties)

  def getMailboxExportRequestStatus(self, user, request_id):
    """Gets the status of an mailbox export request

    Args:
      user: string, the user whose mailbox were requested
      request_id: string, the request_id

    Returns:
      A dict containing the result of the get operation."""

    uri = self._serviceUrl('mail/export', user=user+'/'+request_id)
    try:
      return self._GetProperties(uri)
    except gdata.service.RequestError as e:
      raise gdata.apps.service.AppsForYourDomainException(e.args[0])

  def getAllMailboxExportRequestsStatus(self):
    """Gets the status of all mailbox export requests for the domain

    Args:
      None

    Returns:
      list results of the POST operation
    """

    uri = self._serviceUrl('mail/export')
    return self._GetPropertiesList(uri)


  def deleteMailboxExportRequest(self, user, request_id):
    """Deletes the request for mailbox export

   Args:
     user: string, the user whose mailbox were requested
     request_id: string, the request_id

   Returns:
     Nothing
   """

    uri = self._serviceUrl('mail/export', user=user+'/'+request_id)
    try:
      return self._DeleteProperties(uri)
    except gdata.service.RequestError as e:
      raise gdata.apps.service.AppsForYourDomainException(e.args[0])
