Storing user-specific data

repl.it Authentication API

We'll take a quick look at how we can fetch the repl.it user_name of a visitor to our web page, and store some data relevant to them in the replit db for use on subsequent visits of theirs.

The repl.it Authentication API can also provide us with the user_id (a unique numerical value) and their user_roles, such as 'Teacher', 'Moderator', etc. Thanks to mat1 for their tutorial on this topic!

Security

Don't rely on this to protect any of your own or other users' sensitive information.

Code walkthrough

Let's take a look at the following example, which incorporates repl.it authentication and touches upon some other topics we've seen previously, including Flask, the replit database, Jinja templates, and the time module:

Accessing request headers

try:
    user_name = request.headers['X-Replit-User-Name']

except:
    user_name = None

auth = True if user_name else False
  • we try to fetch the 'X-Replit-User-Name' from the page request headers, which should be there if the user is currently authorized
  • if this fails, we set user_name to None and thus the subsequent conditional statement will evaluate to False

Logging the time and user

if auth:
    now = time.strftime("%X %x", time.localtime())
  • if a user_name is found, we assign a string-formatted time to now, based on the current time in the user's timezone.

  • "%X %x" is an example of a strftime code; a useful list of these codes can be found at strftime.org

if user_name in db.keys():
    visits = db[user_name]
    visits.append(now) 

else: 
    visits = [now]

db[user_name] = visits
  • we check to see if there is a key in the db equal to user_name
  • if there is, we get the associated value (a list), and .append() now to it
  • if there isn't we create a new list with a single value of now
  • we set the value in the db associated with the key user_name to our new or updated visits list

Jinja template for loop

Look at templates/index.html:

<ul>
    {% for visit in visits %}
    <li>{{ visit }}</li>
    {% endfor %}
</ul>
  • underneath the {% if auth %} statement we see a Jinja for loop, which will create a list element in our page for each visit in the visits list passed to the template by the render_template() function in main.py

Repl.it authorization button

<div>
    <script authed="location.reload()" src="https://auth.turbio.repl.co/script.js">
    </script>
</div>

  • this Javascript code snippet results in a Login with Replit button being shown

Customizing the button

Look at static/custom.css (which we've imported in templates/index.html):

button.replit-auth-button {
    text-indent: -9999px;
    line-height: 0;
}
  • the button brought into the page by the script is assigned to a CSS class of .replit-auth-button
  • this (perhaps hacky-looking) code visually 'removes' the original text from the button
button.replit-auth-button::after {    
  content: "Authorize...";
  text-indent: 0;
  display: block;
  line-height: initial;
  font-family: Cambria, serif;
  padding: 3px;
}
  • ::after creates a pseudo-element which adds what's in the content property after any other children in the selected element