| <!DOCTYPE html> |
| <html> |
| <head> |
| <meta http-equiv="content-type" content="text/html;charset=utf-8"> |
| <title>basic_with_auth</title> |
| <link rel="stylesheet" href="/css/pycco.css"> |
| </head> |
| <body> |
| <div id="background"></div> |
| <div id='container'> |
| <div class='section'> |
| <div class='docs'><h1>basic_with_auth</h1></div> |
| </div> |
| <div class='clearall'> |
| <div class='section' id='section-0'> |
| <div class='docs'> |
| <div class='octowrap'> |
| <a class='octothorpe' href='#section-0'>#</a> |
| </div> |
| <p>If you have not yet seen the source in <a href="/examples/basic.html">basic</a>, please take a look.</p> |
| </div> |
| <div class='code'> |
| </div> |
| </div> |
| <div class='clearall'></div> |
| <div class='section' id='section-1'> |
| <div class='docs'> |
| <div class='octowrap'> |
| <a class='octothorpe' href='#section-1'>#</a> |
| </div> |
| </div> |
| <div class='code'> |
| <div class="highlight"><pre><span class="kn">import</span> <span class="n">endpoints</span> |
| <span class="kn">from</span> <span class="nn">google.appengine.ext</span> <span class="kn">import</span> <span class="n">ndb</span> |
| <span class="kn">from</span> <span class="nn">protorpc</span> <span class="kn">import</span> <span class="n">remote</span> |
| |
| <span class="kn">from</span> <span class="nn">endpoints_proto_datastore.ndb</span> <span class="kn">import</span> <span class="n">EndpointsModel</span></pre></div> |
| </div> |
| </div> |
| <div class='clearall'></div> |
| <div class='section' id='section-2'> |
| <div class='docs'> |
| <div class='octowrap'> |
| <a class='octothorpe' href='#section-2'>#</a> |
| </div> |
| <p>In this model definition, we have added an extra field <code>owner</code> to the model |
| defined in <a href="/examples/basic.html">basic</a>. 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.</p> |
| </div> |
| <div class='code'> |
| <div class="highlight"><pre><span class="k">class</span> <span class="nc">MyModel</span><span class="p">(</span><span class="n">EndpointsModel</span><span class="p">):</span></pre></div> |
| </div> |
| </div> |
| <div class='clearall'></div> |
| <div class='section' id='section-3'> |
| <div class='docs'> |
| <div class='octowrap'> |
| <a class='octothorpe' href='#section-3'>#</a> |
| </div> |
| <p>By default, the ProtoRPC message schema corresponding to this model will |
| have four fields: <code>attr1</code>, <code>attr2</code>, <code>created</code> and <code>owner</code> |
| in an arbitrary order (the ordering of properties in a dictionary is not |
| guaranteed).</p> |
| </div> |
| <div class='code'> |
| <div class="highlight"><pre> <span class="n">attr1</span> <span class="o">=</span> <span class="n">ndb</span><span class="o">.</span><span class="n">StringProperty</span><span class="p">()</span> |
| <span class="n">attr2</span> <span class="o">=</span> <span class="n">ndb</span><span class="o">.</span><span class="n">StringProperty</span><span class="p">()</span> |
| <span class="n">created</span> <span class="o">=</span> <span class="n">ndb</span><span class="o">.</span><span class="n">DateTimeProperty</span><span class="p">(</span><span class="n">auto_now_add</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span></pre></div> |
| </div> |
| </div> |
| <div class='clearall'></div> |
| <div class='section' id='section-4'> |
| <div class='docs'> |
| <div class='octowrap'> |
| <a class='octothorpe' href='#section-4'>#</a> |
| </div> |
| <p>The three properties above are represented by string fields, but the |
| <code>UserProperty</code> 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 |
| <code>endpoints_proto_datastore.utils</code> and is used to convert to and from the NDB |
| property and the corresponding ProtoRPC field.</p> |
| </div> |
| <div class='code'> |
| <div class="highlight"><pre> <span class="n">owner</span> <span class="o">=</span> <span class="n">ndb</span><span class="o">.</span><span class="n">UserProperty</span><span class="p">()</span></pre></div> |
| </div> |
| </div> |
| <div class='clearall'></div> |
| <div class='section' id='section-5'> |
| <div class='docs'> |
| <div class='octowrap'> |
| <a class='octothorpe' href='#section-5'>#</a> |
| </div> |
| <p>Since we are using auth, we want to test with the |
| <a href="https://developers.google.com/apis-explorer/">Google APIs Explorer</a>. |
| By default, if <code>allowed_client_ids</code> is not specified, this is |
| enabled by default. If you specify <code>allowed_client_ids</code>, you'll |
| need to include <code>endpoints.API_EXPLORER_CLIENT_ID</code> 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.</p> |
| </div> |
| <div class='code'> |
| <div class="highlight"><pre><span class="nd">@endpoints.api</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s">'myapi'</span><span class="p">,</span> <span class="n">version</span><span class="o">=</span><span class="s">'v1'</span><span class="p">,</span> <span class="n">description</span><span class="o">=</span><span class="s">'My Little API'</span><span class="p">,</span> |
| <span class="n">audiences</span><span class="o">=</span><span class="p">[</span><span class="n">endpoints</span><span class="o">.</span><span class="n">API_EXPLORER_CLIENT_ID</span><span class="p">])</span> |
| <span class="k">class</span> <span class="nc">MyApi</span><span class="p">(</span><span class="n">remote</span><span class="o">.</span><span class="n">Service</span><span class="p">):</span></pre></div> |
| </div> |
| </div> |
| <div class='clearall'></div> |
| <div class='section' id='section-6'> |
| <div class='docs'> |
| <div class='octowrap'> |
| <a class='octothorpe' href='#section-6'>#</a> |
| </div> |
| <p>To specify that this method requires authentication, we can simply set the |
| keyword argument <code>user_required</code> to <code>True</code> in the <code>MyModel.method</code> decorator. The |
| remaining arguments to the decorator are the same as in <a href="/examples/basic.html">basic</a>. Once |
| <code>user_required</code> 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, <code>user_required=True</code> will guarantee that the current user is |
| valid.</p> |
| </div> |
| <div class='code'> |
| <div class="highlight"><pre> <span class="nd">@MyModel.method</span><span class="p">(</span><span class="n">user_required</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> |
| <span class="n">path</span><span class="o">=</span><span class="s">'mymodel'</span><span class="p">,</span> <span class="n">http_method</span><span class="o">=</span><span class="s">'POST'</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s">'mymodel.insert'</span><span class="p">)</span> |
| <span class="k">def</span> <span class="nf">MyModelInsert</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">my_model</span><span class="p">):</span></pre></div> |
| </div> |
| </div> |
| <div class='clearall'></div> |
| <div class='section' id='section-7'> |
| <div class='docs'> |
| <div class='octowrap'> |
| <a class='octothorpe' href='#section-7'>#</a> |
| </div> |
| <p>Since <code>user_required</code> is <code>True</code>, we know <code>endpoints.get_current_user</code> will |
| return a valid user.</p> |
| </div> |
| <div class='code'> |
| <div class="highlight"><pre> <span class="n">my_model</span><span class="o">.</span><span class="n">owner</span> <span class="o">=</span> <span class="n">endpoints</span><span class="o">.</span><span class="n">get_current_user</span><span class="p">()</span></pre></div> |
| </div> |
| </div> |
| <div class='clearall'></div> |
| <div class='section' id='section-8'> |
| <div class='docs'> |
| <div class='octowrap'> |
| <a class='octothorpe' href='#section-8'>#</a> |
| </div> |
| <p>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.</p> |
| </div> |
| <div class='code'> |
| <div class="highlight"><pre> <span class="n">my_model</span><span class="o">.</span><span class="n">put</span><span class="p">()</span> |
| <span class="k">return</span> <span class="n">my_model</span></pre></div> |
| </div> |
| </div> |
| <div class='clearall'></div> |
| <div class='section' id='section-9'> |
| <div class='docs'> |
| <div class='octowrap'> |
| <a class='octothorpe' href='#section-9'>#</a> |
| </div> |
| <p>As above with <code>MyModelInsert</code>, we add <code>user_required=True</code> to the arguments |
| passed to the <code>MyModel.query_method</code> decorator in <a href="/examples/basic.html">basic</a>. Therefore, |
| only queries can be made by a valid user.</p> |
| </div> |
| <div class='code'> |
| <div class="highlight"><pre> <span class="nd">@MyModel.query_method</span><span class="p">(</span><span class="n">user_required</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> |
| <span class="n">path</span><span class="o">=</span><span class="s">'mymodels'</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s">'mymodel.list'</span><span class="p">)</span> |
| <span class="k">def</span> <span class="nf">MyModelList</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">query</span><span class="p">):</span></pre></div> |
| </div> |
| </div> |
| <div class='clearall'></div> |
| <div class='section' id='section-10'> |
| <div class='docs'> |
| <div class='octowrap'> |
| <a class='octothorpe' href='#section-10'>#</a> |
| </div> |
| <p>We only allow users to query the <code>MyModel</code> entities that they have created, |
| so query using owner equal to the current user. Since <code>user_required</code> is |
| set, we know <code>get_current_user</code> will return a valid user.</p> |
| </div> |
| <div class='code'> |
| <div class="highlight"><pre> <span class="k">return</span> <span class="n">query</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">MyModel</span><span class="o">.</span><span class="n">owner</span> <span class="o">==</span> <span class="n">endpoints</span><span class="o">.</span><span class="n">get_current_user</span><span class="p">())</span> |
| </pre></div> |
| </div> |
| </div> |
| <div class='clearall'></div> |
| <div class='section' id='section-11'> |
| <div class='docs'> |
| <div class='octowrap'> |
| <a class='octothorpe' href='#section-11'>#</a> |
| </div> |
| </div> |
| <div class='code'> |
| <div class="highlight"><pre> |
| <span class="n">application</span> <span class="o">=</span> <span class="n">endpoints</span><span class="o">.</span><span class="n">api_server</span><span class="p">([</span><span class="n">MyApi</span><span class="p">],</span> <span class="n">restricted</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span> |
| </pre></div> |
| </div> |
| </div> |
| <div class='clearall'></div> |
| <div class='section' id='section-12'> |
| <div class='docs'> |
| <div class='octowrap'> |
| <a class='octothorpe' href='#section-12'>#</a> |
| </div> |
| <p>Head on to the next sample <a href="/examples/paging.html">paging<a> |
| or head back to the <a href="/">main page</a>.</p> |
| </div> |
| </div> |
| <div class='clearall'></div> |
| </div> |
| </body> |