How to Create a Login Form with Postgres and Python - Part 4: Show Form to Set New Password

Introduction

In this tutorial, we will build a registration system that allows users of your Postgres- and Python-based web application to create a username and password, add a new user to the database, send a confirmation email, handle the confirmation email click, and set a confirmed flag in the database. This article is part four of a five-part series. In this series, we will address the following:

  • Part 1: Build the sign-in form using HTML, CSS, and Javascript. Interaction with the database will be absent from this part 1.
  • Part 2: Validate user input of email and password, create a hash of the user’s password, and compare it to the hash we have in our PostgreSQL database. We’ll use Python for this part of the tutorial. If they verify, we send them on to the rest of your application.
  • Part 3: Email the user a link because they clicked “I forgot my password.”
  • Part 4: Serve the user a modified Javascript/HTML/CSS login form to create a new password.
  • Part 5: Validate, put hash of their new password into the database, and send user to a page with a message.

Overview of this article

In this part 4, we will modify the HTML login form we created in part one so that it can serve more than one purpose. It will actually now have two HTML forms, one for signing in and one for resetting the password.

Assumptions and prerequisites

We’ll assume you have followed the instructions in parts 1, 2, and 3, starting here: here.

The code

Study the code below, paste it into your favorite editor, save the file as “sign/_in.html“, upload to your server’s “/template” folder, and try it out!

<html>
  <head>
    <link rel="shortcut icon" href="favicon.ico" />
    <title>Login</title>
    <meta
     name="description"
     content="Sign in here to play the greatest game ever seen!"
   />
    <!-- In the interest of modularity, once you get this working, -->
    <!-- we recommend you create a stylesheet file and refer to it -->
    <!-- from here using the line below -->
    <!--link href="/css/non-existent-file.css" rel="stylesheet" type="text/css"-->
    <!--  -->
    <script language="JavaScript" type="text/javascript">
      <!--
     /* checkform() is the overall function called from */
     /* our HTML when the user submits the form */
     function checkform (form)
     {
         /* isEmpty() returns true and alerts the user if they left a field empty */
         function isEmpty (fixwhat, s_called)
         {
             if (fixwhat=="")
             {
             alert("Please enter " + s_called);
             return true;
             } else {
             return false;
             }
         }

         /* charCheck() returns false and alerts the user if they used any non-alphanumeric characters */
         function charCheck(fixwhat)
         {
             var validchars = '@-_.0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
             if(isValid(fixwhat,validchars))
             {
                 return true;
             } else {
                 alert("Please use only letters or numbers in this field");
                 return false;
             }
         }

         /* isValid is used by the charCheck() function to look through each 'validchars' one at a time */
         function isValid(string,validchars)
         {
             for (var i=0; i< string.length; i++)
             {
             if (validchars.indexOf(string.charAt(i)) === -1) {return false;}
             }
             return true;
         }

         // Check for empty fields
         if (is_empty (form.t_email.value,"your email address")) { form.t_email.focus();  return false;}
         // IMPORTANT: The "if" below that looks for "frmSignIn" is new code
         // We only need password if they are signing in, NOT if they want a password reset email
         if (form.id.value === "frmSignIn") {
             if (is_empty (form.t_password.value,"your password")) { form.t_password.focus();  return false;}
         }

         //check for weird chars
         if (charCheck(form.t_email.value)===false) {form.t_email.focus(); return false;}
         // IMPORTANT: The "if" below that looks for "frmSignIn" is new code
         if (form.id.value === "frmSignIn") {
             if (charCheck(form.t_password.value)===false) {form.t_password.focus(); return false;}
         }

         return true ;
     }
     //-->
    </script>

    <!-- Some basic styles to set element colors, size, and align our form fields -->
    <!-- As mentioned above, we recommend you place the following CSS into a file -->
    <!-- So that every page of your site can refer to that one CSS file, which -->
    <!-- increases ease of modification in the future. -->
    <style type="text/css">
      html,
      body {
        padding: 1;
        margin: 1;
      }

      input {
        font-size: 16px;
        font-family: Helvetica, sans-serif;
      }

      body {
        background-color: #66aacc;
        font-family: sans-serif, arial, helvetica;
        padding-bottom: 50px;
      }

      .container {
        background-color: #ffffff;
        max-width: 600px;
        margin: 20px auto 0 auto;
        padding: 15px 20px 1px 20px;
      }

      .form-row {
        padding: 10px 0;
        display: flex;
      }

      .form-row label {
        padding-right: 10px;
      }

      .form-row input {
        padding-right: 10px;
        flex: 1;
      }
    </style>
  </head>
  <body>
    <!-- Note: later you may wish to add an include pointer (include) to a common header file here -->
    <!-- or above this mark, depending on other factors. -->
    <!-- Why a common header file? This is so that all pages share the same footer. -->
    <!-- Changing the one header file will change the header of every page on your site. -->
    <!-- For example, you may wish to put your logo and navigation links in this file -->
    <!-- or even have a separate file for header and separate file for navigation. -->

    <!-- The message you see below is why we call this a template -->
    <!-- message is filled in by the Python file as it calls up this HTML -->
    <!-- Later you may wish to separate page title from message -->
    <h1>{{message}}</h1>

    <!-- Note: this 'container' class refers to the '.container' we see in the CSS we wrote above -->
    <div class="container">
      <!-- Set up form type and the file to process user input -->
      <!-- Notice how the onsubmit parameter calls our checkform javascript function -->
      <!-- This checks to make sure the user: -->
      <!-- (a) didn't leave any field empty; and -->
      <!-- (b) used only valid alphanumeric characters -->
      <form
       id="frmSignIn"
       name="frmSignIn"
       action="/sign_in?stage=login"
       method="post"
       onsubmit="return checkform(this);"
     >
        <!-- text box for user to enter their Email address -->
        <!-- Notice our input has an id of 't_email'. -->
        <!-- This is used by our checkform javascript function. -->
        <div class="form-row">
          <label for="Email">Email address:</label>
          <input type="text" id="t_email" name="t_email" />
        </div>

        <!-- text box for user to create a Password -->
        <!-- Notice our input has an id of 't_password'. -->
        <!-- This is used by our checkform javascript function. -->
        <div class="form-row">
          <label for="Email">Password:</label>
          <input type="text" id="t_password" name="t_password" />
        </div>

        <!-- button for user to submit the form -->
        <div class="form-row">
          <input type="submit" id="btn_submit_sign_in" value="Sign In" />
        </div>

        <!-- Close our form -->
      </form>
      <!-- ------------------- -->
      <!-- Password reset form -->
      <!-- ------------------- -->
      <h2>I forgot my password</h2>
      <form
       id="frmResetPassword"
       name="frmResetPassword"
       action='/sign_in?stage=forgot&ID_user={{request.args.get("ID_user")}}'
       method="post"
       onsubmit="return checkform(this);"
     >
        <div class="form-row">
          <label for="Email">Email address:</label>
          <input type="text" id="t_email" name="t_email" />
        </div>

        <div class="form-row">
          <input
           type="submit"
           id="btn_submit_reset"
           value="Send me a password reset link"
         />
        </div>
      </form>
      <!-- Close our container div -->
    </div>

    <!-- Note: later you may wish to add an include pointer (include) to a footer file here. -->
    <!-- This is so that all pages share the same footer. Changing the one footer file will change -->
    <!-- the footer of every page on your site. -->

    <!-- Close the body of our HTML document -->
  </body>
</html>

Conclusion

You’ve now completed part 4 of 5 of creating a registration feature for a web application. In part five we will write more Python to validate and process the new password.

Pilot the ObjectRocket Platform Free!

Try Fully-Managed CockroachDB, Elasticsearch, MongoDB, PostgreSQL (Beta) or Redis.

Get Started

Keep in the know!

Subscribe to our emails and we’ll let you know what’s going on at ObjectRocket. We hate spam and make it easy to unsubscribe.