Automated deployment: Mon Feb 3 09:51:52 UTC 2020 b7bb7c2e31abd420ac3668443d2a57f798120e53

This commit is contained in:
frankie567
2020-02-03 09:51:52 +00:00
parent 06a48f6f84
commit 77a0aa04f2
10 changed files with 355 additions and 3 deletions

View File

@ -424,6 +424,13 @@
Login Login
</a> </a>
</li>
<li class="md-nav__item">
<a href="#logout" class="md-nav__link">
Logout
</a>
</li> </li>
<li class="md-nav__item"> <li class="md-nav__item">
@ -577,6 +584,13 @@
Login Login
</a> </a>
</li>
<li class="md-nav__item">
<a href="#logout" class="md-nav__link">
Logout
</a>
</li> </li>
<li class="md-nav__item"> <li class="md-nav__item">
@ -653,6 +667,14 @@
<blockquote> <blockquote>
<p>Check documentation about <a href="../../../usage/routes/#post-loginname">login route</a>.</p> <p>Check documentation about <a href="../../../usage/routes/#post-loginname">login route</a>.</p>
</blockquote> </blockquote>
<h2 id="logout">Logout<a class="headerlink" href="#logout" title="Permanent link">&para;</a></h2>
<p>This method will remove the authentication cookie:</p>
<div class="admonition success">
<p class="admonition-title"><code>200 OK</code></p>
</div>
<blockquote>
<p>Check documentation about <a href="../../../usage/routes/#post-logoutname">logout route</a>.</p>
</blockquote>
<h2 id="authentication">Authentication<a class="headerlink" href="#authentication" title="Permanent link">&para;</a></h2> <h2 id="authentication">Authentication<a class="headerlink" href="#authentication" title="Permanent link">&para;</a></h2>
<p>This method expects that you provide a valid cookie in the headers.</p> <p>This method expects that you provide a valid cookie in the headers.</p>
<h2 id="next-steps">Next steps<a class="headerlink" href="#next-steps" title="Permanent link">&para;</a></h2> <h2 id="next-steps">Next steps<a class="headerlink" href="#next-steps" title="Permanent link">&para;</a></h2>

View File

@ -588,6 +588,7 @@
<p>You can have <strong>several</strong> authentication methods, e.g. a cookie authentication for browser-based queries and a JWT token authentication for pure API queries.</p> <p>You can have <strong>several</strong> authentication methods, e.g. a cookie authentication for browser-based queries and a JWT token authentication for pure API queries.</p>
<p>When checking authentication, each method is run one after the other. The first method yielding a user wins. If no method yields a user, an <code>HTTPException</code> is raised.</p> <p>When checking authentication, each method is run one after the other. The first method yielding a user wins. If no method yields a user, an <code>HTTPException</code> is raised.</p>
<p>Each defined method will generate a <a href="../../usage/routes/#post-loginname"><code>/login/{name}</code></a> route where <code>name</code> is defined on the authentication method object.</p> <p>Each defined method will generate a <a href="../../usage/routes/#post-loginname"><code>/login/{name}</code></a> route where <code>name</code> is defined on the authentication method object.</p>
<p>Each defined method will generate a <a href="../../usage/routes/#post-logoutname"><code>/logout/{name}</code></a> route where <code>name</code> is defined on the authentication method object.</p>
<h2 id="provided-methods">Provided methods<a class="headerlink" href="#provided-methods" title="Permanent link">&para;</a></h2> <h2 id="provided-methods">Provided methods<a class="headerlink" href="#provided-methods" title="Permanent link">&para;</a></h2>
<ul> <ul>
<li><a href="jwt/">JWT authentication</a></li> <li><a href="jwt/">JWT authentication</a></li>

View File

@ -412,6 +412,13 @@
Login Login
</a> </a>
</li>
<li class="md-nav__item">
<a href="#logout" class="md-nav__link">
Logout
</a>
</li> </li>
<li class="md-nav__item"> <li class="md-nav__item">
@ -577,6 +584,13 @@
Login Login
</a> </a>
</li>
<li class="md-nav__item">
<a href="#logout" class="md-nav__link">
Logout
</a>
</li> </li>
<li class="md-nav__item"> <li class="md-nav__item">
@ -646,6 +660,14 @@
<blockquote> <blockquote>
<p>Check documentation about <a href="../../../usage/routes/#post-loginname">login route</a>.</p> <p>Check documentation about <a href="../../../usage/routes/#post-loginname">login route</a>.</p>
</blockquote> </blockquote>
<h2 id="logout">Logout<a class="headerlink" href="#logout" title="Permanent link">&para;</a></h2>
<p>This method is not applicable to this backend and won't do anything.</p>
<div class="admonition success">
<p class="admonition-title"><code>202 Accepted</code></p>
</div>
<blockquote>
<p>Check documentation about <a href="../../../usage/routes/#post-logoutname">logout route</a>.</p>
</blockquote>
<h2 id="authentication">Authentication<a class="headerlink" href="#authentication" title="Permanent link">&para;</a></h2> <h2 id="authentication">Authentication<a class="headerlink" href="#authentication" title="Permanent link">&para;</a></h2>
<p>This method expects that you provide a <code>Bearer</code> authentication with a valid JWT.</p> <p>This method expects that you provide a <code>Bearer</code> authentication with a valid JWT.</p>
<div class="codehilite"><pre><span></span>curl http://localhost:9000/protected-route -H<span class="s1">&#39;Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI&#39;</span> <div class="codehilite"><pre><span></span>curl http://localhost:9000/protected-route -H<span class="s1">&#39;Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI&#39;</span>

View File

@ -571,7 +571,80 @@
<div class="superfences-tabs"> <div class="superfences-tabs">
<input name="__tabs_1" type="radio" id="__tab_1_0" checked="checked" /> <input name="__tabs_1" type="radio" id="__tab_1_0" checked="checked" />
<label for="__tab_1_0">SQLAlchemy</label> <label for="__tab_1_0">SQLAlchemy</label>
<div class="superfences-content"><div class="codehilite"><pre><span></span> <div class="superfences-content"><div class="codehilite"><pre><span></span><span class="kn">import</span> <span class="nn">databases</span>
<span class="kn">import</span> <span class="nn">sqlalchemy</span>
<span class="kn">from</span> <span class="nn">fastapi</span> <span class="kn">import</span> <span class="n">FastAPI</span>
<span class="kn">from</span> <span class="nn">fastapi_users</span> <span class="kn">import</span> <span class="n">FastAPIUsers</span><span class="p">,</span> <span class="n">models</span>
<span class="kn">from</span> <span class="nn">fastapi_users.authentication</span> <span class="kn">import</span> <span class="n">JWTAuthentication</span>
<span class="kn">from</span> <span class="nn">fastapi_users.db</span> <span class="kn">import</span> <span class="n">SQLAlchemyBaseUserTable</span><span class="p">,</span> <span class="n">SQLAlchemyUserDatabase</span>
<span class="kn">from</span> <span class="nn">sqlalchemy.ext.declarative</span> <span class="kn">import</span> <span class="n">DeclarativeMeta</span><span class="p">,</span> <span class="n">declarative_base</span>
<span class="n">DATABASE_URL</span> <span class="o">=</span> <span class="s2">&quot;sqlite:///./test.db&quot;</span>
<span class="n">SECRET</span> <span class="o">=</span> <span class="s2">&quot;SECRET&quot;</span>
<span class="k">class</span> <span class="nc">User</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">BaseUser</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">class</span> <span class="nc">UserCreate</span><span class="p">(</span><span class="n">User</span><span class="p">,</span> <span class="n">models</span><span class="o">.</span><span class="n">BaseUserCreate</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">class</span> <span class="nc">UserUpdate</span><span class="p">(</span><span class="n">User</span><span class="p">,</span> <span class="n">models</span><span class="o">.</span><span class="n">BaseUserUpdate</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">class</span> <span class="nc">UserDB</span><span class="p">(</span><span class="n">User</span><span class="p">,</span> <span class="n">models</span><span class="o">.</span><span class="n">BaseUserDB</span><span class="p">):</span>
<span class="k">pass</span>
<span class="n">database</span> <span class="o">=</span> <span class="n">databases</span><span class="o">.</span><span class="n">Database</span><span class="p">(</span><span class="n">DATABASE_URL</span><span class="p">)</span>
<span class="n">Base</span><span class="p">:</span> <span class="n">DeclarativeMeta</span> <span class="o">=</span> <span class="n">declarative_base</span><span class="p">()</span>
<span class="k">class</span> <span class="nc">UserTable</span><span class="p">(</span><span class="n">Base</span><span class="p">,</span> <span class="n">SQLAlchemyBaseUserTable</span><span class="p">):</span>
<span class="k">pass</span>
<span class="n">engine</span> <span class="o">=</span> <span class="n">sqlalchemy</span><span class="o">.</span><span class="n">create_engine</span><span class="p">(</span>
<span class="n">DATABASE_URL</span><span class="p">,</span> <span class="n">connect_args</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;check_same_thread&quot;</span><span class="p">:</span> <span class="kc">False</span><span class="p">}</span>
<span class="p">)</span>
<span class="n">Base</span><span class="o">.</span><span class="n">metadata</span><span class="o">.</span><span class="n">create_all</span><span class="p">(</span><span class="n">engine</span><span class="p">)</span>
<span class="n">users</span> <span class="o">=</span> <span class="n">UserTable</span><span class="o">.</span><span class="n">__table__</span>
<span class="n">user_db</span> <span class="o">=</span> <span class="n">SQLAlchemyUserDatabase</span><span class="p">(</span><span class="n">UserDB</span><span class="p">,</span> <span class="n">database</span><span class="p">,</span> <span class="n">users</span><span class="p">)</span>
<span class="n">auth_backends</span> <span class="o">=</span> <span class="p">[</span>
<span class="n">JWTAuthentication</span><span class="p">(</span><span class="n">secret</span><span class="o">=</span><span class="n">SECRET</span><span class="p">,</span> <span class="n">lifetime_seconds</span><span class="o">=</span><span class="mi">3600</span><span class="p">),</span>
<span class="p">]</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">FastAPI</span><span class="p">()</span>
<span class="n">fastapi_users</span> <span class="o">=</span> <span class="n">FastAPIUsers</span><span class="p">(</span>
<span class="n">user_db</span><span class="p">,</span> <span class="n">auth_backends</span><span class="p">,</span> <span class="n">User</span><span class="p">,</span> <span class="n">UserCreate</span><span class="p">,</span> <span class="n">UserUpdate</span><span class="p">,</span> <span class="n">UserDB</span><span class="p">,</span> <span class="n">SECRET</span><span class="p">,</span>
<span class="p">)</span>
<span class="n">app</span><span class="o">.</span><span class="n">include_router</span><span class="p">(</span><span class="n">fastapi_users</span><span class="o">.</span><span class="n">router</span><span class="p">,</span> <span class="n">prefix</span><span class="o">=</span><span class="s2">&quot;/users&quot;</span><span class="p">,</span> <span class="n">tags</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;users&quot;</span><span class="p">])</span>
<span class="nd">@fastapi_users</span><span class="o">.</span><span class="n">on_after_register</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">on_after_register</span><span class="p">(</span><span class="n">user</span><span class="p">:</span> <span class="n">User</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;User </span><span class="si">{user.id}</span><span class="s2"> has registered.&quot;</span><span class="p">)</span>
<span class="nd">@fastapi_users</span><span class="o">.</span><span class="n">on_after_forgot_password</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">on_after_forgot_password</span><span class="p">(</span><span class="n">user</span><span class="p">:</span> <span class="n">User</span><span class="p">,</span> <span class="n">token</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;User </span><span class="si">{user.id}</span><span class="s2"> has forgot their password. Reset token: </span><span class="si">{token}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">on_event</span><span class="p">(</span><span class="s2">&quot;startup&quot;</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">startup</span><span class="p">():</span>
<span class="k">await</span> <span class="n">database</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">on_event</span><span class="p">(</span><span class="s2">&quot;shutdown&quot;</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">shutdown</span><span class="p">():</span>
<span class="k">await</span> <span class="n">database</span><span class="o">.</span><span class="n">disconnect</span><span class="p">()</span>
</pre></div></div> </pre></div></div>
<input name="__tabs_1" type="radio" id="__tab_1_1" /> <input name="__tabs_1" type="radio" id="__tab_1_1" />
<label for="__tab_1_1">MongoDB</label> <label for="__tab_1_1">MongoDB</label>
@ -628,7 +701,58 @@
</pre></div></div> </pre></div></div>
<input name="__tabs_1" type="radio" id="__tab_1_2" /> <input name="__tabs_1" type="radio" id="__tab_1_2" />
<label for="__tab_1_2">Tortoise ORM</label> <label for="__tab_1_2">Tortoise ORM</label>
<div class="superfences-content"><div class="codehilite"><pre><span></span> <div class="superfences-content"><div class="codehilite"><pre><span></span><span class="kn">from</span> <span class="nn">fastapi</span> <span class="kn">import</span> <span class="n">FastAPI</span>
<span class="kn">from</span> <span class="nn">fastapi_users</span> <span class="kn">import</span> <span class="n">FastAPIUsers</span><span class="p">,</span> <span class="n">models</span>
<span class="kn">from</span> <span class="nn">fastapi_users.authentication</span> <span class="kn">import</span> <span class="n">JWTAuthentication</span>
<span class="kn">from</span> <span class="nn">fastapi_users.db</span> <span class="kn">import</span> <span class="n">TortoiseBaseUserModel</span><span class="p">,</span> <span class="n">TortoiseUserDatabase</span>
<span class="kn">from</span> <span class="nn">tortoise.contrib.starlette</span> <span class="kn">import</span> <span class="n">register_tortoise</span>
<span class="n">DATABASE_URL</span> <span class="o">=</span> <span class="s2">&quot;sqlite://./test.db&quot;</span>
<span class="n">SECRET</span> <span class="o">=</span> <span class="s2">&quot;SECRET&quot;</span>
<span class="k">class</span> <span class="nc">User</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">BaseUser</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">class</span> <span class="nc">UserCreate</span><span class="p">(</span><span class="n">User</span><span class="p">,</span> <span class="n">models</span><span class="o">.</span><span class="n">BaseUserCreate</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">class</span> <span class="nc">UserUpdate</span><span class="p">(</span><span class="n">User</span><span class="p">,</span> <span class="n">models</span><span class="o">.</span><span class="n">BaseUserUpdate</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">class</span> <span class="nc">UserDB</span><span class="p">(</span><span class="n">User</span><span class="p">,</span> <span class="n">models</span><span class="o">.</span><span class="n">BaseUserDB</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">class</span> <span class="nc">UserModel</span><span class="p">(</span><span class="n">TortoiseBaseUserModel</span><span class="p">):</span>
<span class="k">pass</span>
<span class="n">user_db</span> <span class="o">=</span> <span class="n">TortoiseUserDatabase</span><span class="p">(</span><span class="n">UserDB</span><span class="p">,</span> <span class="n">UserModel</span><span class="p">)</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">FastAPI</span><span class="p">()</span>
<span class="n">register_tortoise</span><span class="p">(</span><span class="n">app</span><span class="p">,</span> <span class="n">db_url</span><span class="o">=</span><span class="n">DATABASE_URL</span><span class="p">,</span> <span class="n">modules</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;models&quot;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&quot;test&quot;</span><span class="p">]})</span>
<span class="n">auth_backends</span> <span class="o">=</span> <span class="p">[</span>
<span class="n">JWTAuthentication</span><span class="p">(</span><span class="n">secret</span><span class="o">=</span><span class="n">SECRET</span><span class="p">,</span> <span class="n">lifetime_seconds</span><span class="o">=</span><span class="mi">3600</span><span class="p">),</span>
<span class="p">]</span>
<span class="n">fastapi_users</span> <span class="o">=</span> <span class="n">FastAPIUsers</span><span class="p">(</span>
<span class="n">user_db</span><span class="p">,</span> <span class="n">auth_backends</span><span class="p">,</span> <span class="n">User</span><span class="p">,</span> <span class="n">UserCreate</span><span class="p">,</span> <span class="n">UserUpdate</span><span class="p">,</span> <span class="n">UserDB</span><span class="p">,</span> <span class="n">SECRET</span><span class="p">,</span>
<span class="p">)</span>
<span class="n">app</span><span class="o">.</span><span class="n">include_router</span><span class="p">(</span><span class="n">fastapi_users</span><span class="o">.</span><span class="n">router</span><span class="p">,</span> <span class="n">prefix</span><span class="o">=</span><span class="s2">&quot;/users&quot;</span><span class="p">,</span> <span class="n">tags</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;users&quot;</span><span class="p">])</span>
<span class="nd">@fastapi_users</span><span class="o">.</span><span class="n">on_after_register</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">on_after_register</span><span class="p">(</span><span class="n">user</span><span class="p">:</span> <span class="n">User</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;User </span><span class="si">{user.id}</span><span class="s2"> has registered.&quot;</span><span class="p">)</span>
<span class="nd">@fastapi_users</span><span class="o">.</span><span class="n">on_after_forgot_password</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">on_after_forgot_password</span><span class="p">(</span><span class="n">user</span><span class="p">:</span> <span class="n">User</span><span class="p">,</span> <span class="n">token</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;User </span><span class="si">{user.id}</span><span class="s2"> has forgot their password. Reset token: </span><span class="si">{token}</span><span class="s2">&quot;</span><span class="p">)</span>
</pre></div></div> </pre></div></div>
</div> </div>
<h2 id="what-now">What now?<a class="headerlink" href="#what-now" title="Permanent link">&para;</a></h2> <h2 id="what-now">What now?<a class="headerlink" href="#what-now" title="Permanent link">&para;</a></h2>

View File

@ -454,6 +454,13 @@
After forgot password After forgot password
</a> </a>
</li>
<li class="md-nav__item">
<a href="#after-update" class="md-nav__link">
After update
</a>
</li> </li>
</ul> </ul>
@ -603,6 +610,13 @@
After forgot password After forgot password
</a> </a>
</li>
<li class="md-nav__item">
<a href="#after-update" class="md-nav__link">
After update
</a>
</li> </li>
</ul> </ul>
@ -693,6 +707,21 @@
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;User </span><span class="si">{user.id}</span><span class="s2"> has forgot their password. Reset token: </span><span class="si">{token}</span><span class="s2">&quot;</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;User </span><span class="si">{user.id}</span><span class="s2"> has forgot their password. Reset token: </span><span class="si">{token}</span><span class="s2">&quot;</span><span class="p">)</span>
</pre></div> </pre></div>
<h3 id="after-update">After update<a class="headerlink" href="#after-update" title="Permanent link">&para;</a></h3>
<p>This event handler is called after a successful update user request. It is called with <strong>three arguments</strong>:</p>
<ul>
<li>The <strong>user</strong> which was updated.</li>
<li>The dictionary containing the updated fields.</li>
<li>The original <strong><code>Request</code> object</strong>.</li>
</ul>
<p>It may be useful if you wish for example update your user in a data analytics or customer success platform.</p>
<p>You can define it as an <code>async</code> or standard method.</p>
<p>Example:</p>
<div class="codehilite"><pre><span></span><span class="nd">@fastapi_users</span><span class="o">.</span><span class="n">on_after_update</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">on_after_update</span><span class="p">(</span><span class="n">user</span><span class="p">:</span> <span class="n">User</span><span class="p">,</span> <span class="n">updated_user_data</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Any</span><span class="p">],</span> <span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;User </span><span class="si">{user.id}</span><span class="s2"> has been updated with the following data: </span><span class="si">{updated_user_data}</span><span class="s2">&quot;</span><span class="p">)</span>
</pre></div>
<h2 id="next-steps">Next steps<a class="headerlink" href="#next-steps" title="Permanent link">&para;</a></h2> <h2 id="next-steps">Next steps<a class="headerlink" href="#next-steps" title="Permanent link">&para;</a></h2>
<p>Check out a <a href="../full_example/">full example</a> that will show you the big picture.</p> <p>Check out a <a href="../full_example/">full example</a> that will show you the big picture.</p>

File diff suppressed because one or more lines are too long

Binary file not shown.

74
src/full_sqlalchemy.py Normal file
View File

@ -0,0 +1,74 @@
import databases
import sqlalchemy
from fastapi import FastAPI
from fastapi_users import FastAPIUsers, models
from fastapi_users.authentication import JWTAuthentication
from fastapi_users.db import SQLAlchemyBaseUserTable, SQLAlchemyUserDatabase
from sqlalchemy.ext.declarative import DeclarativeMeta, declarative_base
DATABASE_URL = "sqlite:///./test.db"
SECRET = "SECRET"
class User(models.BaseUser):
pass
class UserCreate(User, models.BaseUserCreate):
pass
class UserUpdate(User, models.BaseUserUpdate):
pass
class UserDB(User, models.BaseUserDB):
pass
database = databases.Database(DATABASE_URL)
Base: DeclarativeMeta = declarative_base()
class UserTable(Base, SQLAlchemyBaseUserTable):
pass
engine = sqlalchemy.create_engine(
DATABASE_URL, connect_args={"check_same_thread": False}
)
Base.metadata.create_all(engine)
users = UserTable.__table__
user_db = SQLAlchemyUserDatabase(UserDB, database, users)
auth_backends = [
JWTAuthentication(secret=SECRET, lifetime_seconds=3600),
]
app = FastAPI()
fastapi_users = FastAPIUsers(
user_db, auth_backends, User, UserCreate, UserUpdate, UserDB, SECRET,
)
app.include_router(fastapi_users.router, prefix="/users", tags=["users"])
@fastapi_users.on_after_register()
def on_after_register(user: User):
print(f"User {user.id} has registered.")
@fastapi_users.on_after_forgot_password()
def on_after_forgot_password(user: User, token: str):
print(f"User {user.id} has forgot their password. Reset token: {token}")
@app.on_event("startup")
async def startup():
await database.connect()
@app.on_event("shutdown")
async def shutdown():
await database.disconnect()

52
src/full_tortoise.py Normal file
View File

@ -0,0 +1,52 @@
from fastapi import FastAPI
from fastapi_users import FastAPIUsers, models
from fastapi_users.authentication import JWTAuthentication
from fastapi_users.db import TortoiseBaseUserModel, TortoiseUserDatabase
from tortoise.contrib.starlette import register_tortoise
DATABASE_URL = "sqlite://./test.db"
SECRET = "SECRET"
class User(models.BaseUser):
pass
class UserCreate(User, models.BaseUserCreate):
pass
class UserUpdate(User, models.BaseUserUpdate):
pass
class UserDB(User, models.BaseUserDB):
pass
class UserModel(TortoiseBaseUserModel):
pass
user_db = TortoiseUserDatabase(UserDB, UserModel)
app = FastAPI()
register_tortoise(app, db_url=DATABASE_URL, modules={"models": ["test"]})
auth_backends = [
JWTAuthentication(secret=SECRET, lifetime_seconds=3600),
]
fastapi_users = FastAPIUsers(
user_db, auth_backends, User, UserCreate, UserUpdate, UserDB, SECRET,
)
app.include_router(fastapi_users.router, prefix="/users", tags=["users"])
@fastapi_users.on_after_register()
def on_after_register(user: User):
print(f"User {user.id} has registered.")
@fastapi_users.on_after_forgot_password()
def on_after_forgot_password(user: User, token: str):
print(f"User {user.id} has forgot their password. Reset token: {token}")

View File

@ -507,6 +507,13 @@
POST /login/{name} POST /login/{name}
</a> </a>
</li>
<li class="md-nav__item">
<a href="#post-logoutname" class="md-nav__link">
POST /logout/{name}
</a>
</li> </li>
<li class="md-nav__item"> <li class="md-nav__item">
@ -691,6 +698,13 @@
POST /login/{name} POST /login/{name}
</a> </a>
</li>
<li class="md-nav__item">
<a href="#post-logoutname" class="md-nav__link">
POST /logout/{name}
</a>
</li> </li>
<li class="md-nav__item"> <li class="md-nav__item">
@ -880,6 +894,20 @@
<span class="p">}</span> <span class="p">}</span>
</pre></div> </pre></div>
</div>
<h3 id="post-logoutname"><code>POST /logout/{name}</code><a class="headerlink" href="#post-logoutname" title="Permanent link">&para;</a></h3>
<p>Logout the authenticated user against the method named <code>name</code>. Check the corresponding <a href="../../configuration/authentication/">authentication method</a> to view the success response.</p>
<div class="admonition fail">
<p class="admonition-title"><code>401 Unauthorized</code></p>
<p>Missing token or inactive user.</p>
</div>
<div class="admonition success">
<p class="admonition-title"><code>200 OK</code></p>
<p>The logout process was successful.</p>
</div>
<div class="admonition success">
<p class="admonition-title"><code>202 Accepted</code></p>
<p>The logout process is not applicable for this authentication backend (e.g. JWT).</p>
</div> </div>
<h3 id="post-forgot-password"><code>POST /forgot-password</code><a class="headerlink" href="#post-forgot-password" title="Permanent link">&para;</a></h3> <h3 id="post-forgot-password"><code>POST /forgot-password</code><a class="headerlink" href="#post-forgot-password" title="Permanent link">&para;</a></h3>
<p>Request a reset password procedure. Will generate a temporary token and call the <code>on_after_forgot_password</code> <a href="../../configuration/router/#event-handlers">event handlers</a> if the user exists.</p> <p>Request a reset password procedure. Will generate a temporary token and call the <code>on_after_forgot_password</code> <a href="../../configuration/router/#event-handlers">event handlers</a> if the user exists.</p>