{"componentChunkName":"component---src-pages-markdown-remark-fields-slug-js","path":"/engineering/guest-post/securing-flask-api-with-jwt/","result":{"data":{"markdownRemark":{"id":"493661c3-a0e2-5195-aaa2-674b3eb14e67","excerpt":"Authentication is an essential part of any web application. But unfortunately, it is not always easy to implement. What is Authentication? Authentication is a…","html":"<p>Authentication is an essential part of any web application. But unfortunately, it is not always easy to implement.</p>\n<h2 id=\"what-is-authentication\" style=\"position:relative;\"><a href=\"#what-is-authentication\" aria-label=\"what is authentication permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is Authentication?</h2>\n<p>Authentication is a process of verifying that an entity is who they claim to be. For example, a user might authenticate by providing a username and password. If the username and password are valid, the system will check if the user can access the resource. After the system checks the user's details against its database and if the details are valid, the user is thus authenticated and can access available resources.</p>\n<h2 id=\"authentication-factors\" style=\"position:relative;\"><a href=\"#authentication-factors\" aria-label=\"authentication factors permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Authentication Factors</h2>\n<p>The following factors are used to authenticate a user.</p>\n<h3 id=\"single-factor-authentication\" style=\"position:relative;\"><a href=\"#single-factor-authentication\" aria-label=\"single factor authentication permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Single-factor Authentication</h3>\n<p>This authentication is used when a user provides a username/email/phone number and a password. This is the most common and weakest authentication factor. The user simply inputs the email and password, and the system checks if the data is valid; if valid, the user gets authenticated and can access the resource. What happens if another person who is not a legitimate user tries to access the resource? The system denies access to the resource.</p>\n<h3 id=\"multi-factor-authentication\" style=\"position:relative;\"><a href=\"#multi-factor-authentication\" aria-label=\"multi factor authentication permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><a href=\"https://www.loginradius.com/multi-factor-authentication/\">Multi-factor Authentication</a></h3>\n<p>This authentication uses more than one factor to authenticate a user. For example, the user tries to log in with, say, email and password; if the data is correct, a code is sent to the user's phone number, and the user is asked to input the code. If the user enters the code, the user gets logged in; otherwise, the user is not authenticated. Some applications even go a step further by not using two factors but using three factors.</p>\n<h2 id=\"types-of-authentication\" style=\"position:relative;\"><a href=\"#types-of-authentication\" aria-label=\"types of authentication permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Types of Authentication</h2>\n<p>There are three types of authentication, as follows:</p>\n<ol>\n<li><strong>Knowledge Authentication</strong>: The user is asked something that only they can provide or know -- e.g., password. This is the most common type and also the easiest.</li>\n<li><strong>Property Authentication</strong>: The user is asked for something they own or possess. For example, they can use a hardware authentication device like YubiKey or an authenticator app on their phone. The idea is that users will be asked to set an authentication factor that verifies the identity more securely. This isn’t always used alone; it’s used alongside another authentication type, say, <code>Knowledge authentication</code>.</li>\n<li><strong>Biological Authentication</strong>: The user is asked to verify their identity using something biologically unique to them -- e.g., a fingerprint or iris scan.</li>\n</ol>\n<p>In most applications, knowledge and property authentication are used as an extra layer of authentication.</p>\n<h2 id=\"authentication-vs-authorization\" style=\"position:relative;\"><a href=\"#authentication-vs-authorization\" aria-label=\"authentication vs authorization permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Authentication vs. Authorization</h2>\n<p>The following are the differences between authentication and authorization:</p>\n<ol>\n<li>Authentication verifies identity (usually through credential validation)) while authorization grants or denies permissions to a user.</li>\n<li>Authentication is used to verify that users are who they say they are. Authorization is used to verify that a user has permission to do something.</li>\n</ol>\n<h2 id=\"starter-application\" style=\"position:relative;\"><a href=\"#starter-application\" aria-label=\"starter application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Starter Application</h2>\n<p>In this tutorial, you'll work on authentication in flask middleware for an existing API built with <a href=\"https://flask.palletsprojects.com/en/2.0.x/\">Flask</a> and <a href=\"https://pymongo.readthedocs.io/en/stable/\">PyMongo</a>. The API is a book library API using which users can create books and upload cover images for the books and relevant data. PyMongo is used to connect to the mongo database. You'll use the PyJWT library to generate and verify JWT tokens for auth in flask.  </p>\n<blockquote>\n<p>You can learn <a href=\"https://www.loginradius.com/blog/engineering/guest-post/jwt-authentication-best-practices-and-when-to-use/\">more about JSON Web Tokens (JWT) here</a>.</p>\n</blockquote>\n<p>To get started, clone the repository and set up the application by running the following commands:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"bash\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">git clone https://github.com/LoginRadius/engineering-blog-samples.git </span><span class=\"mtk3\"># Clone the repository</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">cd</span><span class=\"mtk1\"> /Flask/loginRadius-flask-auth </span><span class=\"mtk3\"># change directory</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">python3 -m venv env </span><span class=\"mtk3\"># create virtual environment; if you&#39;re using Windows, `py -m venv env`</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">source</span><span class=\"mtk1\"> env/bin/activate </span><span class=\"mtk3\"># activate virtual environment, if you&#39;re using windows, env/Scripts/activate</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">pip install -r requirements.txt </span><span class=\"mtk3\"># install dependencies</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\"># https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/</span></span></code></pre>\n<p>The application is now set up and ready to run. You can run the app using the command <code>flask run</code> in the project directory. You can test that all the endpoints are working by testing the app in an API testing tool, like Postman.</p>\n<h2 id=\"authentication-middleware\" style=\"position:relative;\"><a href=\"#authentication-middleware\" aria-label=\"authentication middleware permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Authentication Middleware</h2>\n<p>As you've noticed, anybody can access the API; you need to restrict access to the API. Create new book data if they have the correct data, then add, delete, and update book data, but you don't want that. To do this, you need to implement an authentication middleware.</p>\n<p>When we talk about authentication with flask, middlewares are created in Flask by creating a decorator; a function can have multiple middlewares, and the order matters a lot. </p>\n<p>To create your auth middleware, you need to install PyJWT -- the library you'll use to generate tokens. You’ll also use Pillow to alter image data before saving them to disk. Run the following command to install the packages:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"bash\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">pip install pyjwt pillow</span></span></code></pre>\n<p>You need to add a secret key to your application; this is what you should pass to JWT.</p>\n<p>Add the following to your <code>app.py</code> file below the app declaration.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\"># app = Flask(__name__)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">SECRET_KEY = os.environ.get(</span><span class=\"mtk8\">&#39;SECRET_KEY&#39;</span><span class=\"mtk1\">) </span><span class=\"mtk4\">or</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;this is a secret&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">print</span><span class=\"mtk1\">(SECRET_KEY)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">app.config[</span><span class=\"mtk8\">&#39;SECRET_KEY&#39;</span><span class=\"mtk1\">] = SECRET_KEY</span></span></code></pre>\n<p>Let's create a file called <code>auth_middleware.py</code> in the root of your application and place the following inside this file:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> functools </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> wraps</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> jwt</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> flask </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> request, abort</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> flask </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> current_app</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> models</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">token_required</span><span class=\"mtk1\">(</span><span class=\"mtk12\">f</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">@wraps</span><span class=\"mtk1\">(f)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">decorated</span><span class=\"mtk1\">(*</span><span class=\"mtk12\">args</span><span class=\"mtk1\">, **</span><span class=\"mtk12\">kwargs</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        token = </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Authorization&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk4\">in</span><span class=\"mtk1\"> request.headers:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            token = request.headers[</span><span class=\"mtk8\">&quot;Authorization&quot;</span><span class=\"mtk1\">].split(</span><span class=\"mtk8\">&quot; &quot;</span><span class=\"mtk1\">)[</span><span class=\"mtk7\">1</span><span class=\"mtk1\">]</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> token:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Authentication Token is missing!&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Unauthorized&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">401</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            data=jwt.decode(token, current_app.config[</span><span class=\"mtk8\">&quot;SECRET_KEY&quot;</span><span class=\"mtk1\">], </span><span class=\"mtk12\">algorithms</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;HS256&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            current_user=models.User().get_by_id(data[</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> current_user </span><span class=\"mtk4\">is</span><span class=\"mtk1\"> </span><span class=\"mtk4\">None</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Invalid Authentication token!&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Unauthorized&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">401</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> current_user[</span><span class=\"mtk8\">&quot;active&quot;</span><span class=\"mtk1\">]:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                abort(</span><span class=\"mtk7\">403</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Something went wrong&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">500</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> f(current_user, *args, **kwargs)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> decorated</span></span></code></pre>\n<p>The function above is simply a decorator function. Inside this function, you check if there is an <code>Authorization</code> field in the headers part of the request; if this is missing, you return an authorization error.</p>\n<p>Next, you check if it exists but is not valid; if it is not valid, you also return an authorization error.</p>\n<p>If everything goes fine, then the view function is called. As you can see, you return <code>f(current_user, *args, **kwargs)</code>, where <code>f</code> is the next decorator or function that's being called after this decorator -- in your case, the view function, which means that the first argument of any view function that uses this decorator must be <code>current_user</code>.</p>\n<h2 id=\"auth-routes\" style=\"position:relative;\"><a href=\"#auth-routes\" aria-label=\"auth routes permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Auth Routes</h2>\n<p>You currently have a route to creating a new user, but you don't have one to log in. From what you have above, you're checking if the token passed as the header is valid, but now the question is -- how do you get to know the token. Basically, the login route fetches the token and sends it to the client.</p>\n<p>Add the following function below the <code>add_user</code> function:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/users/login&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;POST&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">login</span><span class=\"mtk1\">():</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        data = request.json</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> data:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Please provide user details&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Bad request&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk3\"># validate input</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        is_validated = validate_email_and_password(data.get(</span><span class=\"mtk8\">&#39;email&#39;</span><span class=\"mtk1\">), data.get(</span><span class=\"mtk8\">&#39;password&#39;</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> is_validated </span><span class=\"mtk4\">is</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> </span><span class=\"mtk4\">True</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk10\">dict</span><span class=\"mtk1\">(</span><span class=\"mtk12\">message</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&#39;Invalid data&#39;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">data</span><span class=\"mtk1\">=</span><span class=\"mtk4\">None</span><span class=\"mtk1\">, </span><span class=\"mtk12\">error</span><span class=\"mtk1\">=is_validated), </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = User().login(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            data[</span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            data[</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">]</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> user:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk3\"># token should expire after 24 hrs</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                user[</span><span class=\"mtk8\">&quot;token&quot;</span><span class=\"mtk1\">] = jwt.encode(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    {</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">: user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">]},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    app.config[</span><span class=\"mtk8\">&quot;SECRET_KEY&quot;</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk12\">algorithm</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;HS256&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Successfully fetched auth token&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: user</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Something went wrong&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                }, </span><span class=\"mtk7\">500</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Error fetching auth token!, invalid email or password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Unauthorized&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }, </span><span class=\"mtk7\">404</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Something went wrong!&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }, </span><span class=\"mtk7\">500</span></span></code></pre>\n<h2 id=\"protecting-api-routes-in-flask\" style=\"position:relative;\"><a href=\"#protecting-api-routes-in-flask\" aria-label=\"protecting api routes in flask permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Protecting API Routes in Flask</h2>\n<p>So far, you've been able to create your auth middleware, but you need to use this middleware to protect routes. All you need to do is to pass this middleware immediately after the <code>app.route</code> middleware, then make <code>current_user</code> the first argument of the view function, as follows:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;/&#39;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">user</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify(current_user)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;/&lt;pdt_id&gt;&#39;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">product</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">, </span><span class=\"mtk12\">pdt_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify(Product.find({</span><span class=\"mtk8\">&#39;user_id&#39;</span><span class=\"mtk1\">: pdt_id}))</span></span></code></pre>\n<p>Add this middleware (<code>@token_required</code>) to every function you only want authenticated users to access. In the end, your whole <code>app.py</code> file should look as follows.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> jwt, os</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> dotenv </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> load_dotenv</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> flask </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> Flask, request, jsonify</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> save_image </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> save_pic</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> validate </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> validate_book, validate_email_and_password, validate_user</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">load_dotenv()</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">app = Flask(</span><span class=\"mtk12\">__name__</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">SECRET_KEY = os.environ.get(</span><span class=\"mtk8\">&#39;SECRET_KEY&#39;</span><span class=\"mtk1\">) </span><span class=\"mtk4\">or</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;this is a secret&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">print</span><span class=\"mtk1\">(SECRET_KEY)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">app.config[</span><span class=\"mtk8\">&#39;SECRET_KEY&#39;</span><span class=\"mtk1\">] = SECRET_KEY</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> models </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> Books, User</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> auth_middleware </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> token_required</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">hello</span><span class=\"mtk1\">():</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Hello World!&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/users/&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;POST&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">add_user</span><span class=\"mtk1\">():</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = request.json</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> user:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Please provide user details&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Bad request&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        is_validated = validate_user(**user)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> is_validated </span><span class=\"mtk4\">is</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> </span><span class=\"mtk4\">True</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk10\">dict</span><span class=\"mtk1\">(</span><span class=\"mtk12\">message</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&#39;Invalid data&#39;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">data</span><span class=\"mtk1\">=</span><span class=\"mtk4\">None</span><span class=\"mtk1\">, </span><span class=\"mtk12\">error</span><span class=\"mtk1\">=is_validated), </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = User().create(**user)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> user:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;User already exists&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Conflict&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">409</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Successfully created new user&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: user</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }, </span><span class=\"mtk7\">201</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Something went wrong&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }, </span><span class=\"mtk7\">500</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/users/login&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;POST&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">login</span><span class=\"mtk1\">():</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        data = request.json</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> data:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Please provide user details&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Bad request&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk3\"># validate input</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        is_validated = validate_email_and_password(data.get(</span><span class=\"mtk8\">&#39;email&#39;</span><span class=\"mtk1\">), data.get(</span><span class=\"mtk8\">&#39;password&#39;</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> is_validated </span><span class=\"mtk4\">is</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> </span><span class=\"mtk4\">True</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk10\">dict</span><span class=\"mtk1\">(</span><span class=\"mtk12\">message</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&#39;Invalid data&#39;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">data</span><span class=\"mtk1\">=</span><span class=\"mtk4\">None</span><span class=\"mtk1\">, </span><span class=\"mtk12\">error</span><span class=\"mtk1\">=is_validated), </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = User().login(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            data[</span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            data[</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">]</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> user:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk3\"># token should expire after 24 hrs</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                user[</span><span class=\"mtk8\">&quot;token&quot;</span><span class=\"mtk1\">] = jwt.encode(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    {</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">: user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">]},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    app.config[</span><span class=\"mtk8\">&quot;SECRET_KEY&quot;</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk12\">algorithm</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;HS256&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Successfully fetched auth token&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: user</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Something went wrong&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                }, </span><span class=\"mtk7\">500</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Error fetching auth token!, invalid email or password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Unauthorized&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }, </span><span class=\"mtk7\">404</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Something went wrong!&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }, </span><span class=\"mtk7\">500</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/users/&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;GET&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_current_user</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;successfully retrieved user profile&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: current_user</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    })</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/users/&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;PUT&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">update_user</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = request.json</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> user.get(</span><span class=\"mtk8\">&quot;name&quot;</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            user = User().update(current_user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">], user[</span><span class=\"mtk8\">&quot;name&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;successfully updated account&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: user</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }), </span><span class=\"mtk7\">201</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Invalid data, you can only update your account name!&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Bad Request&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }, </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;failed to update account&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/users/&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;DELETE&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">disable_user</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        User().disable_account(current_user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;successfully disabled acount&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">204</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;failed to disable account&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/books/&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;POST&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">add_book</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = </span><span class=\"mtk10\">dict</span><span class=\"mtk1\">(request.form)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> book:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Invalid data, you need to give the book title, cover image, author id,&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Bad Request&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> request.files[</span><span class=\"mtk8\">&quot;cover_image&quot;</span><span class=\"mtk1\">]:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;cover image is required&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book[</span><span class=\"mtk8\">&quot;image_url&quot;</span><span class=\"mtk1\">] = request.host_url+</span><span class=\"mtk8\">&quot;static/books/&quot;</span><span class=\"mtk1\">+save_pic(request.files[</span><span class=\"mtk8\">&quot;cover_image&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book[</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">] = current_user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">]</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        is_validated = validate_book(**book)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> is_validated </span><span class=\"mtk4\">is</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> </span><span class=\"mtk4\">True</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Invalid data&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: is_validated</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = Books().create(**book)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> book:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;The book has been created by user&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Conflict&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;successfully created a new book&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: book</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">201</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;failed to create a new book&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">500</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/books/&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;GET&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_books</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        books = Books().get_by_user_id(current_user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;successfully retrieved all books&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: books</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;failed to retrieve all books&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">500</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/books/&lt;book_id&gt;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;GET&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_book</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">, </span><span class=\"mtk12\">book_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = Books().get_by_id(book_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> book:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Book not found&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Not Found&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">404</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;successfully retrieved a book&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: book</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Something went wrong&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">500</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/books/&lt;book_id&gt;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;PUT&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">update_book</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">, </span><span class=\"mtk12\">book_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = Books().get_by_id(book_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> book </span><span class=\"mtk4\">or</span><span class=\"mtk1\"> book[</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">] != current_user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">]:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Book not found for user&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Not found&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">404</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = request.form</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> book.get(</span><span class=\"mtk8\">&#39;cover_image&#39;</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            book[</span><span class=\"mtk8\">&quot;image_url&quot;</span><span class=\"mtk1\">] = request.host_url+</span><span class=\"mtk8\">&quot;static/books/&quot;</span><span class=\"mtk1\">+save_pic(request.files[</span><span class=\"mtk8\">&quot;cover_image&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = Books().update(book_id, **book)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;successfully updated a book&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: book</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">201</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;failed to update a book&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/books/&lt;book_id&gt;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;DELETE&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">delete_book</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">, </span><span class=\"mtk12\">book_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = Books().get_by_id(book_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> book </span><span class=\"mtk4\">or</span><span class=\"mtk1\"> book[</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">] != current_user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">]:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Book not found for user&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Not found&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">404</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        Books().delete(book_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;successfully deleted a book&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">204</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;failed to delete a book&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.errorhandler</span><span class=\"mtk1\">(</span><span class=\"mtk7\">403</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">forbidden</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Forbidden&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }), </span><span class=\"mtk7\">403</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.errorhandler</span><span class=\"mtk1\">(</span><span class=\"mtk7\">404</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">forbidden</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Endpoint Not Found&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }), </span><span class=\"mtk7\">404</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk12\">__name__</span><span class=\"mtk1\"> == </span><span class=\"mtk8\">&quot;__main__&quot;</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    app.run(</span><span class=\"mtk12\">debug</span><span class=\"mtk1\">=</span><span class=\"mtk4\">True</span><span class=\"mtk1\">)</span></span></code></pre>\n<p>Before running the application, let's look at the <code>save_pic</code> function inside the <code>save_image.py</code> file. This is the function responsible for saving uploaded pictures.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> PIL </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> Image</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> secrets, os</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> flask </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> current_app </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> app</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">save_pic</span><span class=\"mtk1\">(</span><span class=\"mtk12\">picture</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    file_name = secrets.token_hex(</span><span class=\"mtk7\">8</span><span class=\"mtk1\">) +os.path.splitext(picture.filename)[</span><span class=\"mtk7\">1</span><span class=\"mtk1\">]</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> os.path.isdir(os.path.join(app.root_path, </span><span class=\"mtk8\">&#39;static&#39;</span><span class=\"mtk1\">)):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        os.mkdir(os.path.join(app.root_path,</span><span class=\"mtk8\">&quot;static&quot;</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        os.mkdir(os.path.join(app.root_path,</span><span class=\"mtk8\">&quot;static/images&quot;</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        os.mkdir(os.path.join(app.root_path,</span><span class=\"mtk8\">&quot;static/images/books&quot;</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> os.path.isdir(os.path.join(app.root_path, </span><span class=\"mtk8\">&#39;static/images&#39;</span><span class=\"mtk1\">)):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        os.mkdir(os.path.join(app.root_path,</span><span class=\"mtk8\">&quot;static/images&quot;</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        os.mkdir(os.path.join(app.root_path,</span><span class=\"mtk8\">&quot;static/images/books&quot;</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> os.path.isdir(os.path.join(app.root_path, </span><span class=\"mtk8\">&#39;static/images/books&#39;</span><span class=\"mtk1\">)):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        os.mkdir(os.path.join(app.root_path,</span><span class=\"mtk8\">&quot;static/images/books&quot;</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    file_path = os.path.join(app.root_path, </span><span class=\"mtk8\">&quot;static/images/books&quot;</span><span class=\"mtk1\">, file_name)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    picture = Image.open(picture)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    picture.thumbnail((</span><span class=\"mtk7\">150</span><span class=\"mtk1\">, </span><span class=\"mtk7\">150</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    picture.save(file_path)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> file_name</span></span></code></pre>\n<p>You should also add the following functions as helper methods of the <code>User</code> model class.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">disable_account</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    user = db.users.update_one(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        {</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: bson.ObjectId(user_id)},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        {</span><span class=\"mtk8\">&quot;$set&quot;</span><span class=\"mtk1\">: {</span><span class=\"mtk8\">&quot;active&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">False</span><span class=\"mtk1\">}}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    user = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_id(user_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> user</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">encrypt_password</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">password</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> generate_password_hash(password)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">login</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">email</span><span class=\"mtk1\">, </span><span class=\"mtk12\">password</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;&quot;&quot;Login a user&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    user = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_email(email)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> user </span><span class=\"mtk4\">or</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> check_password_hash(user[</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">], password):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    user.pop(</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> user</span></span></code></pre>\n<p>Your <code>models.py</code> file should look as follows:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk8\">&quot;&quot;&quot;Application Models&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> bson, os</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> dotenv </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> load_dotenv</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> pymongo </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> MongoClient</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> werkzeug.security </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> generate_password_hash, check_password_hash</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">load_dotenv()</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">DATABASE_URL=os.environ.get(</span><span class=\"mtk8\">&#39;DATABASE_URL&#39;</span><span class=\"mtk1\">) </span><span class=\"mtk4\">or</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;mongodb://localhost:27017/myDatabase&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">print</span><span class=\"mtk1\">(DATABASE_URL)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">client = MongoClient(DATABASE_URL)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">db = client.myDatabase</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">class</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Books</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;&quot;&quot;Books Model&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">__init__</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">create</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">title</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">description</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">image_url</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">category</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Create a new book&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_user_id_and_title(user_id, title)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> book:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        new_book = db.books.insert_one(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;title&quot;</span><span class=\"mtk1\">: title,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;description&quot;</span><span class=\"mtk1\">: description,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;image_url&quot;</span><span class=\"mtk1\">: image_url,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;category&quot;</span><span class=\"mtk1\">: category,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">: user_id</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_id(new_book.inserted_id)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_all</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Get all books&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        books = db.books.find()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> [{**book, </span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(book[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])} </span><span class=\"mtk15\">for</span><span class=\"mtk1\"> book </span><span class=\"mtk4\">in</span><span class=\"mtk1\"> books]</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_by_id</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">book_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Get a book by id&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = db.books.find_one({</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: bson.ObjectId(book_id)})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> book:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">] = </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(book[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> book</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_by_user_id</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Get all books created by a user&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        books = db.books.find({</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">: user_id})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> [{**book, </span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(book[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])} </span><span class=\"mtk15\">for</span><span class=\"mtk1\"> book </span><span class=\"mtk4\">in</span><span class=\"mtk1\"> books]</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_by_category</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">category</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Get all books by category&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        books = db.books.find({</span><span class=\"mtk8\">&quot;category&quot;</span><span class=\"mtk1\">: category})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> [book </span><span class=\"mtk15\">for</span><span class=\"mtk1\"> book </span><span class=\"mtk4\">in</span><span class=\"mtk1\"> books]</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_by_user_id_and_category</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">, </span><span class=\"mtk12\">category</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Get all books by category for a particular user&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        books = db.books.find({</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">: user_id, </span><span class=\"mtk8\">&quot;category&quot;</span><span class=\"mtk1\">: category})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> [{**book, </span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(book[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])} </span><span class=\"mtk15\">for</span><span class=\"mtk1\"> book </span><span class=\"mtk4\">in</span><span class=\"mtk1\"> books]</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_by_user_id_and_title</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">, </span><span class=\"mtk12\">title</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Get a book given its title and author&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = db.books.find_one({</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">: user_id, </span><span class=\"mtk8\">&quot;title&quot;</span><span class=\"mtk1\">: title})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> book:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">] = </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(book[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> book</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">update</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">book_id</span><span class=\"mtk1\">, </span><span class=\"mtk12\">title</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">description</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">image_url</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">category</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Update a book&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        data={}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> title: data[</span><span class=\"mtk8\">&quot;title&quot;</span><span class=\"mtk1\">]=title</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> description: data[</span><span class=\"mtk8\">&quot;description&quot;</span><span class=\"mtk1\">]=description</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> image_url: data[</span><span class=\"mtk8\">&quot;image_url&quot;</span><span class=\"mtk1\">]=image_url</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> category: data[</span><span class=\"mtk8\">&quot;category&quot;</span><span class=\"mtk1\">]=category</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = db.books.update_one(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            {</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: bson.ObjectId(book_id)},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;$set&quot;</span><span class=\"mtk1\">: data</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_id(book_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> book</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">delete</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">book_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Delete a book&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = db.books.delete_one({</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: bson.ObjectId(book_id)})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> book</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">delete_by_user_id</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Delete all books created by a user&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = db.books.delete_many({</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">: bson.ObjectId(user_id)})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> book</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">class</span><span class=\"mtk1\"> </span><span class=\"mtk10\">User</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;&quot;&quot;User Model&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">__init__</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">create</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">email</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">password</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Create a new user&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_email(email)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> user:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        new_user = db.users.insert_one(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;name&quot;</span><span class=\"mtk1\">: name,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk1\">: email,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.encrypt_password(password),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;active&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">True</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_id(new_user.inserted_id)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_all</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Get all users&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        users = db.users.find({</span><span class=\"mtk8\">&quot;active&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">True</span><span class=\"mtk1\">})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> [{**user, </span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])} </span><span class=\"mtk15\">for</span><span class=\"mtk1\"> user </span><span class=\"mtk4\">in</span><span class=\"mtk1\"> users]</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_by_id</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Get a user by id&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = db.users.find_one({</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: bson.ObjectId(user_id), </span><span class=\"mtk8\">&quot;active&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">True</span><span class=\"mtk1\">})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> user:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">] = </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user.pop(</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> user</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_by_email</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">email</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Get a user by email&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = db.users.find_one({</span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk1\">: email, </span><span class=\"mtk8\">&quot;active&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">True</span><span class=\"mtk1\">})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> user:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">] = </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> user</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">update</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">, </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Update a user&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        data = {}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> name:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            data[</span><span class=\"mtk8\">&quot;name&quot;</span><span class=\"mtk1\">] = name</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = db.users.update_one(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            {</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: bson.ObjectId(user_id)},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;$set&quot;</span><span class=\"mtk1\">: data</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_id(user_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> user</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">delete</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Delete a user&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        Books().delete_by_user_id(user_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = db.users.delete_one({</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: bson.ObjectId(user_id)})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_id(user_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> user</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">disable_account</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Disable a user account&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = db.users.update_one(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            {</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: bson.ObjectId(user_id)},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            {</span><span class=\"mtk8\">&quot;$set&quot;</span><span class=\"mtk1\">: {</span><span class=\"mtk8\">&quot;active&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">False</span><span class=\"mtk1\">}}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_id(user_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> user</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">encrypt_password</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">password</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Encrypt password&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> generate_password_hash(password)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">login</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">email</span><span class=\"mtk1\">, </span><span class=\"mtk12\">password</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Login a user&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_email(email)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> user </span><span class=\"mtk4\">or</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> check_password_hash(user[</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">], password):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user.pop(</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> user</span></span></code></pre>\n<p>Here's an example of the user request:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">{</span>\n<span class=\"grvsc-line\">     &quot;name&quot; : &quot;abc xyz&quot;,</span>\n<span class=\"grvsc-line\">     &quot;email&quot; : &quot;xyz@gmail.com&quot;,</span>\n<span class=\"grvsc-line\">     &quot;password&quot; : &quot;Abc@123&quot;</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<p>Here, the name should have two words, and the password should have at least an uppercase later, a lower case letter, a digit, and a special character.</p>\n<p>And an example of the book request:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"11\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">{</span>\n<span class=\"grvsc-line\">    &quot;title&quot;:&quot;name of book&quot;,</span>\n<span class=\"grvsc-line\">    &quot;cover_image&quot;: &quot;path to image file locally&quot;,</span>\n<span class=\"grvsc-line\">    &quot;category&quot;: &quot;[&#39;romance&#39;, &#39;peotry&#39;, &#39;politics&#39;, &#39;picture book&#39;, &#39;science&#39;, &#39;fantasy&#39;, &#39;horror&#39;, &#39;thriller&#39;],</span>\n<span class=\"grvsc-line\">    &quot;description&quot;:&quot;description&quot;,</span>\n<span class=\"grvsc-line\">    &quot;user_id&quot;:&quot;user_id&quot;</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<p>While passing a book request, pass it via the <code>form-data</code> tab in Postman.</p>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>This article has explained flask JWT authentication .</p>\n<p>In some cases, handling flask authentication yourself may not be good enough or efficient -- to overcome this, you can simply use third-party authentication providers like LoginRadius. You can check out this tutorial to learn how to add LoginRadius to your Flask application.</p>\n<p>You can find the complete code for this article on <a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/Flask/loginRadius-flask-auth\">Github</a>. You can reach out to me on <a href=\"https://twitter.com/bkoiki950\">Twitter</a> if you've any questions.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n</style>","headings":[{"value":"What is Authentication?","depth":2},{"value":"Authentication Factors","depth":2},{"value":"Single-factor Authentication","depth":3},{"value":"Multi-factor Authentication","depth":3},{"value":"Types of Authentication","depth":2},{"value":"Authentication vs. Authorization","depth":2},{"value":"Starter Application","depth":2},{"value":"Authentication Middleware","depth":2},{"value":"Auth Routes","depth":2},{"value":"Protecting API Routes in Flask","depth":2},{"value":"Conclusion","depth":2}],"fields":{"slug":"/engineering/guest-post/securing-flask-api-with-jwt/"},"frontmatter":{"metatitle":null,"metadescription":null,"description":"This tutorial helps you build a simple Flask API and demonstrates how to secure it using JWT. In the end, you can test your API authentication using a sample schema.","title":"Using JWT Flask JWT Authentication- A Quick Guide","canonical":null,"date":"December 09, 2021","updated_date":null,"tags":["Flask","JWT","API"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/1cfc51c7d9ade423f3b1992809ba5b1b/2ad7f/coverImage.webp","srcSet":"/static/1cfc51c7d9ade423f3b1992809ba5b1b/1c9b5/coverImage.webp 200w,\n/static/1cfc51c7d9ade423f3b1992809ba5b1b/f1752/coverImage.webp 400w,\n/static/1cfc51c7d9ade423f3b1992809ba5b1b/2ad7f/coverImage.webp 800w,\n/static/1cfc51c7d9ade423f3b1992809ba5b1b/e7405/coverImage.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Babatunde Koiki","github":"Babatunde13","bio":"He is an experienced software engineer with great passion for building reliable, scalable, and maintainable products. And he loves great documentation. When he is not writing code, he hangs out with friends or watches movies.","avatar":null}}}},"pageContext":{"id":"493661c3-a0e2-5195-aaa2-674b3eb14e67","fields__slug":"/engineering/guest-post/securing-flask-api-with-jwt/","__params":{"fields__slug":"engineering"}}},"staticQueryHashes":["1171199041","1384082988","1711371485","1753898100","2100481360","229320306","23180105","528864852"]}