#!/usr/bin/env python
#
# Copyright 2007 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.
#




"""A handler that exports various App Engine services over HTTP.

You can export this handler in your app by adding it to the builtins section:

builtins:
- remote_api: on

This will add remote_api serving to the path /_ah/remote_api.

You can also add it to your handlers section, e.g.:

  handlers:
  - url: /remote_api(/.*)?
    script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py

You can use remote_api_stub to remotely access services exported by this
handler. See the documentation in remote_api_stub.py for details on how to do
this.

The handler supports several forms of authentication. By default, it
checks that the user is an admin using the Users API, similar to specifying
"login: admin" in the app.yaml file. It also supports a 'custom header' mode
which can be used in certain scenarios.

To configure the custom header mode, edit an appengine_config file (the same
one you may use to configure appstats) to include a line like this:

  remoteapi_CUSTOM_ENVIRONMENT_AUTHENTICATION = (
      'HTTP_X_APPENGINE_INBOUND_APPID', ['otherappid'] )

See the ConfigDefaults class below for the full set of options available.
"""









import google
import hashlib
import logging
import os
import pickle
import wsgiref.handlers
import yaml

from google.appengine.api import api_base_pb
from google.appengine.api import apiproxy_stub
from google.appengine.api import apiproxy_stub_map
from google.appengine.api import datastore_types
from google.appengine.api import lib_config
from google.appengine.api import oauth
from google.appengine.api import users
from google.appengine.datastore import datastore_pb
from google.appengine.datastore import datastore_rpc
from google.appengine.ext import webapp
from google.appengine.ext.db import metadata
from google.appengine.ext.remote_api import remote_api_pb
from google.appengine.ext.remote_api import remote_api_services
from google.appengine.runtime import apiproxy_errors
from google.appengine.datastore import entity_pb


class ConfigDefaults(object):
  """Configurable constants.

  To override remote_api configuration values, define values like this
  in your appengine_config.py file (in the root of your app):

    remoteapi_CUSTOM_ENVIRONMENT_AUTHENTICATION = (
        'HTTP_X_APPENGINE_INBOUND_APPID', ['otherappid'] )

  You may wish to base this file on sample_appengine_config.py.
  """

  # Allow other App Engine applications to use remote_api with special forms
  # of authentication which appear in the environment. This is a pair,
  # ( environment variable name, [ list of valid values ] ). Some examples:
  # * Allow other applications to use remote_api:
  #   remoteapi_CUSTOM_ENVIRONMENT_AUTHENTICATION = (
  #       'HTTP_X_APPENGINE_INBOUND_APPID', ['otherappid'] )
  # * Allow two specific users (who need not be admins):
  #   remoteapi_CUSTOM_ENVIRONMENT_AUTHENTICATION = ('USER_ID',
  #                                                  [ '1234', '1111' ] )





  # Note that this an alternate to the normal users.is_current_user_admin
  # check--either one may pass.
  CUSTOM_ENVIRONMENT_AUTHENTICATION = ()
  _ALLOW_OAUTH = False


config = lib_config.register('remoteapi', ConfigDefaults.__dict__)


class RemoteDatastoreStub(apiproxy_stub.APIProxyStub):
  """Provides a stub that permits execution of stateful datastore queries.

  Some operations aren't possible using the standard interface. Notably,
  datastore RunQuery operations internally store a cursor that is referenced in
  later Next calls, and cleaned up at the end of each request. Because every
  call to ApiCallHandler takes place in its own request, this isn't possible.

  To work around this, RemoteDatastoreStub provides its own implementation of
  RunQuery that immediately returns the query results.
  """

  def __init__(self, service='datastore_v3', _test_stub_map=None):
    """Constructor.

    Args:
      service: The name of the service
      _test_stub_map: An APIProxyStubMap to use for testing purposes.
    """
    super(RemoteDatastoreStub, self).__init__(service)
    if _test_stub_map:
      self.__call = _test_stub_map.MakeSyncCall
    else:
      self.__call = apiproxy_stub_map.MakeSyncCall

  def _Dynamic_RunQuery(self, request, response):
    """Handle a RunQuery request.

    We handle RunQuery by executing a Query and a Next and returning the result
    of the Next request.

    This method is DEPRECATED, but left in place for older clients.
    """
    runquery_response = datastore_pb.QueryResult()
    self.__call('datastore_v3', 'RunQuery', request, runquery_response)
    if runquery_response.result_size() > 0:

      response.CopyFrom(runquery_response)
      return


    next_request = datastore_pb.NextRequest()
    next_request.mutable_cursor().CopyFrom(runquery_response.cursor())
    next_request.set_count(request.limit())
    self.__call('datastore_v3', 'Next', next_request, response)

  def _Dynamic_TransactionQuery(self, request, response):
    if not request.has_ancestor():
      raise apiproxy_errors.ApplicationError(
          datastore_pb.Error.BAD_REQUEST,
          'No ancestor in transactional query.')

    app_id = datastore_types.ResolveAppId(None)
    if (datastore_rpc._GetDatastoreType(app_id) !=
        datastore_rpc.BaseConnection.HIGH_REPLICATION_DATASTORE):
      raise apiproxy_errors.ApplicationError(
          datastore_pb.Error.BAD_REQUEST,
          'remote_api supports transactional queries only in the '
          'high-replication datastore.')


    entity_group_key = entity_pb.Reference()
    entity_group_key.CopyFrom(request.ancestor())
    group_path = entity_group_key.mutable_path()
    root = entity_pb.Path_Element()
    root.MergeFrom(group_path.element(0))
    group_path.clear_element()
    group_path.add_element().CopyFrom(root)
    eg_element = group_path.add_element()
    eg_element.set_type(metadata.EntityGroup.KIND_NAME)
    eg_element.set_id(metadata.EntityGroup.ID)


    begin_request = datastore_pb.BeginTransactionRequest()
    begin_request.set_app(app_id)
    tx = datastore_pb.Transaction()
    self.__call('datastore_v3', 'BeginTransaction', begin_request, tx)


    request.mutable_transaction().CopyFrom(tx)
    self.__call('datastore_v3', 'RunQuery', request, response.mutable_result())


    get_request = datastore_pb.GetRequest()
    get_request.mutable_transaction().CopyFrom(tx)
    get_request.add_key().CopyFrom(entity_group_key)
    get_response = datastore_pb.GetResponse()
    self.__call('datastore_v3', 'Get', get_request, get_response)
    entity_group = get_response.entity(0)


    response.mutable_entity_group_key().CopyFrom(entity_group_key)
    if entity_group.has_entity():
      response.mutable_entity_group().CopyFrom(entity_group.entity())


    self.__call('datastore_v3', 'Commit', tx, datastore_pb.CommitResponse())

  def _Dynamic_Transaction(self, request, response):
    """Handle a Transaction request.

    We handle transactions by accumulating Put and Delete requests on the client
    end, as well as recording the key and hash of Get requests. When Commit is
    called, Transaction is invoked, which verifies that all the entities in the
    precondition list still exist and their hashes match, then performs a
    transaction of its own to make the updates.
    """

    begin_request = datastore_pb.BeginTransactionRequest()
    begin_request.set_app(os.environ['APPLICATION_ID'])
    begin_request.set_allow_multiple_eg(request.allow_multiple_eg())
    tx = datastore_pb.Transaction()
    self.__call('datastore_v3', 'BeginTransaction', begin_request, tx)


    preconditions = request.precondition_list()
    if preconditions:
      get_request = datastore_pb.GetRequest()
      get_request.mutable_transaction().CopyFrom(tx)
      for precondition in preconditions:
        key = get_request.add_key()
        key.CopyFrom(precondition.key())
      get_response = datastore_pb.GetResponse()
      self.__call('datastore_v3', 'Get', get_request, get_response)
      entities = get_response.entity_list()
      assert len(entities) == request.precondition_size()
      for precondition, entity in zip(preconditions, entities):
        if precondition.has_hash() != entity.has_entity():
          raise apiproxy_errors.ApplicationError(
              datastore_pb.Error.CONCURRENT_TRANSACTION,
              "Transaction precondition failed.")
        elif entity.has_entity():
          entity_hash = hashlib.sha1(entity.entity().Encode()).digest()
          if precondition.hash() != entity_hash:
            raise apiproxy_errors.ApplicationError(
                datastore_pb.Error.CONCURRENT_TRANSACTION,
                "Transaction precondition failed.")


    if request.has_puts():
      put_request = request.puts()
      put_request.mutable_transaction().CopyFrom(tx)
      self.__call('datastore_v3', 'Put', put_request, response)


    if request.has_deletes():
      delete_request = request.deletes()
      delete_request.mutable_transaction().CopyFrom(tx)
      self.__call('datastore_v3', 'Delete', delete_request,
                  datastore_pb.DeleteResponse())


    self.__call('datastore_v3', 'Commit', tx, datastore_pb.CommitResponse())

  def _Dynamic_GetIDsXG(self, request, response):
    self._Dynamic_GetIDs(request, response, is_xg=True)

  def _Dynamic_GetIDs(self, request, response, is_xg=False):
    """Fetch unique IDs for a set of paths."""

    for entity in request.entity_list():
      assert entity.property_size() == 0
      assert entity.raw_property_size() == 0
      assert entity.entity_group().element_size() == 0
      lastpart = entity.key().path().element_list()[-1]
      assert lastpart.id() == 0 and not lastpart.has_name()


    begin_request = datastore_pb.BeginTransactionRequest()
    begin_request.set_app(os.environ['APPLICATION_ID'])
    begin_request.set_allow_multiple_eg(is_xg)
    tx = datastore_pb.Transaction()
    self.__call('datastore_v3', 'BeginTransaction', begin_request, tx)


    self.__call('datastore_v3', 'Put', request, response)


    self.__call('datastore_v3', 'Rollback', tx, api_base_pb.VoidProto())



SERVICE_PB_MAP = remote_api_services.SERVICE_PB_MAP

class ApiCallHandler(webapp.RequestHandler):
  """A webapp handler that accepts API calls over HTTP and executes them."""

  LOCAL_STUBS = {
      'remote_datastore': RemoteDatastoreStub('remote_datastore'),
  }

  OAUTH_SCOPE = 'https://www.googleapis.com/auth/appengine.apis'

  def CheckIsAdmin(self):
    user_is_authorized = False
    if users.is_current_user_admin():
      user_is_authorized = True
    if not user_is_authorized and config.CUSTOM_ENVIRONMENT_AUTHENTICATION:
      if len(config.CUSTOM_ENVIRONMENT_AUTHENTICATION) == 2:
        var, values = config.CUSTOM_ENVIRONMENT_AUTHENTICATION
        if os.getenv(var) in values:
          user_is_authorized = True
      else:
        logging.warning('remoteapi_CUSTOM_ENVIRONMENT_AUTHENTICATION is '
                        'configured incorrectly.')

    if not user_is_authorized and config._ALLOW_OAUTH:
      try:
        user_is_authorized = (
            oauth.is_current_user_admin(_scope=self.OAUTH_SCOPE))
      except oauth.OAuthRequestError:

        pass
    if not user_is_authorized:
      self.response.set_status(401)
      self.response.out.write(
          'You must be logged in as an administrator to access this.')
      self.response.headers['Content-Type'] = 'text/plain'
      return False
    if 'X-appcfg-api-version' not in self.request.headers:
      self.response.set_status(403)
      self.response.out.write('This request did not contain a necessary header')
      self.response.headers['Content-Type'] = 'text/plain'
      return False
    return True

  def CheckConfigIsValid(self):

    if config.CUSTOM_ENVIRONMENT_AUTHENTICATION and config._ALLOW_OAUTH:
      self.response.set_status(400)
      self.response.out.write('You cannot enable both OAuth authentication '
                              '(remoteapi__ALLOW_OAUTH) and '
                              'custom authentication '
                              '(remoteapi_CUSTOM_ENVIRONMENT_AUTHENTICATION).')
      return False
    return True


  def get(self):
    """Handle a GET. Just show an info page."""
    if not self.CheckConfigIsValid() or not self.CheckIsAdmin():
      return

    rtok = self.request.get('rtok', '0')
    app_info = {
        'app_id': os.environ['APPLICATION_ID'],
        'rtok': rtok
        }

    self.response.headers['Content-Type'] = 'text/plain'
    self.response.out.write(yaml.dump(app_info))

  def post(self):
    """Handle POST requests by executing the API call."""
    if not self.CheckConfigIsValid() or not self.CheckIsAdmin():
      return
















    self.response.headers['Content-Type'] = 'text/plain'

    response = remote_api_pb.Response()
    try:
      request = remote_api_pb.Request()



      request.ParseFromString(self.request.body)
      response_data = self.ExecuteRequest(request)
      response.set_response(response_data.Encode())
      self.response.set_status(200)
    except Exception, e:
      logging.exception('Exception while handling %s', request)
      self.response.set_status(200)



      response.set_exception(pickle.dumps(e))
      if isinstance(e, apiproxy_errors.ApplicationError):
        application_error = response.mutable_application_error()
        application_error.set_code(e.application_error)
        application_error.set_detail(e.error_detail)
    self.response.out.write(response.Encode())

  def ExecuteRequest(self, request):
    """Executes an API invocation and returns the response object."""
    service = request.service_name()
    method = request.method()
    service_methods = SERVICE_PB_MAP.get(service, {})
    request_class, response_class = service_methods.get(method, (None, None))
    if not request_class:
      raise apiproxy_errors.CallNotFoundError()

    request_data = request_class()
    request_data.ParseFromString(request.request())
    response_data = response_class()

    if service in self.LOCAL_STUBS:
      self.LOCAL_STUBS[service].MakeSyncCall(service, method, request_data,
                                             response_data)
    else:
      apiproxy_stub_map.MakeSyncCall(service, method, request_data,
                                     response_data)

    return response_data

  def InfoPage(self):
    """Renders an information page."""
    return """
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html><head>
<title>App Engine API endpoint.</title>
</head><body>
<h1>App Engine API endpoint.</h1>
<p>This is an endpoint for the App Engine remote API interface.
Point your stubs (google.appengine.ext.remote_api.remote_api_stub) here.</p>
</body>
</html>"""

application = webapp.WSGIApplication([('.*', ApiCallHandler)])


def main():
  wsgiref.handlers.CGIHandler().run(application)


if __name__ == '__main__':
  main()
