blob: 8568d6a01a27d36db15b149d6a502214232cb298 [file] [log] [blame]
# If you have not yet seen the source in basic/main.py, please take a look.
import endpoints
from google.appengine.ext import ndb
from protorpc import remote
from endpoints_proto_datastore.ndb import EndpointsModel
# In this model definition, we have added an extra field "owner" to the model
# defined in basic/main.py. Since using auth, we will save the current user and
# query by the current user, so saving a user property on each entity will allow
# us to do this.
class MyModel(EndpointsModel):
# By default, the ProtoRPC message schema corresponding to this model will
# have four fields: attr1, attr2, created and owner
# in an arbitrary order (the ordering of properties in a dictionary is not
# guaranteed).
attr1 = ndb.StringProperty()
attr2 = ndb.StringProperty()
created = ndb.DateTimeProperty(auto_now_add=True)
# The three properties above are represented by string fields, but the
# UserProperty below is represented in the ProtoRPC message schema as a
# message field -- a field whose value is itself a message. To hold a user
# property, a custom ProtoRPC message class is defined in
# endpoints_proto_datastore.utils and is used to convert to and from the NDB
# property and the corresponding ProtoRPC field.
owner = ndb.UserProperty()
# Since we are using auth, we want to test with the Google APIs Explorer:
# https://developers.google.com/apis-explorer/
# By default, if allowed_client_ids is not specified, this is enabled by
# default. If you specify allowed_client_ids, you'll need to include
# endpoints.API_EXPLORER_CLIENT_ID in this list. This is necessary for auth
# tokens obtained by the API Explorer (on behalf of users) to be considered
# valid by our API.
@endpoints.api(name='myapi', version='v1', description='My Little API')
class MyApi(remote.Service):
# To specify that this method requires authentication, we can simply set the
# keyword argument user_required to True in the MyModel.method decorator. The
# remaining arguments to the decorator are the same as in basic/main.py. Once
# user_required is set, the method will first determine if a user has been
# detected from the token sent with the request (if any was sent it all) and
# will return an HTTP 401 Unauthorized if no valid user is detected. In the
# case of a 401, the method will not be executed. Conversely, if method
# execution occurs, user_required=True will guarantee that the current user is
# valid.
@MyModel.method(user_required=True,
path='mymodel', http_method='POST', name='mymodel.insert')
def MyModelInsert(self, my_model):
# Since user_required is True, we know endpoints.get_current_user will
# return a valid user.
my_model.owner = endpoints.get_current_user()
# Also note, since we don't override the default ProtoRPC message schema,
# API users can send an owner object in the request, but we overwrite the
# model property with the current user before the entity is inserted into
# the datastore and this put operation will only occur if a valid token
# identifying the user was sent in the Authorization header.
my_model.put()
return my_model
# As above with MyModelInsert, we add user_required=True to the arguments
# passed to the MyModel.query_method decorator in basic/main.py. Therefore,
# only queries can be made by a valid user.
@MyModel.query_method(user_required=True,
path='mymodels', name='mymodel.list')
def MyModelList(self, query):
# We only allow users to query the MyModel entities that they have created,
# so query using owner equal to the current user. Since user_required is
# set, we know get_current_user will return a valid user.
return query.filter(MyModel.owner == endpoints.get_current_user())
application = endpoints.api_server([MyApi], restricted=False)