thirdparty/google_appengine/google/appengine/api/datastore_file_stub.py
changeset 2273 e4cb9c53db3e
parent 1278 a7766286a7be
child 2309 be1b94099f2d
--- a/thirdparty/google_appengine/google/appengine/api/datastore_file_stub.py	Tue Apr 21 16:28:13 2009 +0000
+++ b/thirdparty/google_appengine/google/appengine/api/datastore_file_stub.py	Fri Apr 24 14:16:00 2009 +0000
@@ -37,6 +37,7 @@
 
 import datetime
 import logging
+import md5
 import os
 import struct
 import sys
@@ -145,7 +146,8 @@
                datastore_file,
                history_file,
                require_indexes=False,
-               service_name='datastore_v3'):
+               service_name='datastore_v3',
+               trusted=False):
     """Constructor.
 
     Initializes and loads the datastore from the backing files, if they exist.
@@ -159,6 +161,8 @@
       require_indexes: bool, default False.  If True, composite indexes must
           exist in index.yaml for queries that need them.
       service_name: Service name expected for all calls.
+      trusted: bool, default False.  If True, this stub allows an app to
+        access the data of another app.
     """
     super(DatastoreFileStub, self).__init__(service_name)
 
@@ -167,6 +171,7 @@
     self.__app_id = app_id
     self.__datastore_file = datastore_file
     self.__history_file = history_file
+    self.SetTrusted(trusted)
 
     self.__entities = {}
 
@@ -207,6 +212,31 @@
     self.__query_history = {}
     self.__schema_cache = {}
 
+  def SetTrusted(self, trusted):
+    """Set/clear the trusted bit in the stub.
+
+    This bit indicates that the app calling the stub is trusted. A
+    trusted app can write to datastores of other apps.
+
+    Args:
+      trusted: boolean.
+    """
+    self.__trusted = trusted
+
+  def __ValidateAppId(self, app_id):
+    """Verify that this is the stub for app_id.
+
+    Args:
+      app_id: An application ID.
+
+    Raises:
+      datastore_errors.BadRequestError: if this is not the stub for app_id.
+    """
+    if not self.__trusted and app_id != self.__app_id:
+      raise datastore_errors.BadRequestError(
+          'app %s cannot access app %s\'s data' % (self.__app_id, app_id))
+
+
   def _AppKindForKey(self, key):
     """ Get (app, kind) tuple from given key.
 
@@ -336,7 +366,7 @@
           return pickle.load(open(filename, 'rb'))
         else:
           logging.warning('Could not read datastore data from %s', filename)
-      except (AttributeError, LookupError, NameError, TypeError,
+      except (AttributeError, LookupError, ImportError, NameError, TypeError,
               ValueError, struct.error, pickle.PickleError), e:
         raise datastore_errors.InternalError(
           'Could not read data from %s. Try running with the '
@@ -394,8 +424,18 @@
   def _Dynamic_Put(self, put_request, put_response):
     clones = []
     for entity in put_request.entity_list():
+      self.__ValidateAppId(entity.key().app())
+
       clone = entity_pb.EntityProto()
       clone.CopyFrom(entity)
+
+      for property in clone.property_list():
+        if property.value().has_uservalue():
+          uid = md5.new(property.value().uservalue().email().lower()).digest()
+          uid = '1' + ''.join(['%02d' % ord(x) for x in uid])[:20]
+          property.mutable_value().mutable_uservalue().set_obfuscated_gaiaid(
+              uid)
+
       clones.append(clone)
 
       assert clone.has_key()
@@ -433,22 +473,24 @@
 
   def _Dynamic_Get(self, get_request, get_response):
     for key in get_request.key_list():
-        app_kind = self._AppKindForKey(key)
+      self.__ValidateAppId(key.app())
+      app_kind = self._AppKindForKey(key)
 
-        group = get_response.add_entity()
-        try:
-          entity = self.__entities[app_kind][key].protobuf
-        except KeyError:
-          entity = None
+      group = get_response.add_entity()
+      try:
+        entity = self.__entities[app_kind][key].protobuf
+      except KeyError:
+        entity = None
 
-        if entity:
-          group.mutable_entity().CopyFrom(entity)
+      if entity:
+        group.mutable_entity().CopyFrom(entity)
 
 
   def _Dynamic_Delete(self, delete_request, delete_response):
     self.__entities_lock.acquire()
     try:
       for key in delete_request.key_list():
+        self.__ValidateAppId(key.app())
         app_kind = self._AppKindForKey(key)
         try:
           del self.__entities[app_kind][key]
@@ -472,6 +514,9 @@
     else:
       self.__tx_lock.release()
 
+    app = query.app()
+    self.__ValidateAppId(app)
+
     if query.has_offset() and query.offset() > _MAX_QUERY_OFFSET:
       raise apiproxy_errors.ApplicationError(
           datastore_pb.Error.BAD_REQUEST, 'Too big query offset.')
@@ -485,8 +530,6 @@
           ('query is too large. may not have more than %s filters'
            ' + sort orders ancestor total' % _MAX_QUERY_COMPONENTS))
 
-    app = query.app()
-
     if self.__require_indexes:
       required, kind, ancestor, props, num_eq_filters = datastore_index.CompositeIndexForQuery(query)
       if required:
@@ -701,6 +744,7 @@
                                              'Cursor %d not found' % cursor)
 
     count = next_request.count()
+
     results_pb = [r._ToPb() for r in results[:count]]
     query_result.result_list().extend(results_pb)
     del results[:count]
@@ -708,6 +752,7 @@
     query_result.set_more_results(len(results) > 0)
 
   def _Dynamic_Count(self, query, integer64proto):
+    self.__ValidateAppId(query.app())
     query_result = datastore_pb.QueryResult()
     self._Dynamic_RunQuery(query, query_result)
     cursor = query_result.cursor().cursor()
@@ -759,6 +804,7 @@
       minfloat = -1e300000
 
     app_str = app_str.value()
+    self.__ValidateAppId(app_str)
 
     kinds = []
 
@@ -816,6 +862,7 @@
       schema.add_kind().CopyFrom(kind_pb)
 
   def _Dynamic_CreateIndex(self, index, id_response):
+    self.__ValidateAppId(index.app_id())
     if index.id() != 0:
       raise apiproxy_errors.ApplicationError(datastore_pb.Error.BAD_REQUEST,
                                              'New index id must be 0.')
@@ -843,10 +890,12 @@
       self.__indexes_lock.release()
 
   def _Dynamic_GetIndices(self, app_str, composite_indices):
+    self.__ValidateAppId(app_str.value())
     composite_indices.index_list().extend(
       self.__indexes.get(app_str.value(), []))
 
   def _Dynamic_UpdateIndex(self, index, void):
+    self.__ValidateAppId(index.app_id())
     stored_index = self.__FindIndex(index)
     if not stored_index:
       raise apiproxy_errors.ApplicationError(datastore_pb.Error.BAD_REQUEST,
@@ -866,6 +915,7 @@
       self.__indexes_lock.release()
 
   def _Dynamic_DeleteIndex(self, index, void):
+    self.__ValidateAppId(index.app_id())
     stored_index = self.__FindIndex(index)
     if not stored_index:
       raise apiproxy_errors.ApplicationError(datastore_pb.Error.BAD_REQUEST,
@@ -888,6 +938,7 @@
       entity_pb.CompositeIndex, if it exists; otherwise None
     """
     app = index.app_id()
+    self.__ValidateAppId(app)
     if app in self.__indexes:
       for stored_index in self.__indexes[app]:
         if index.definition() == stored_index.definition():