AWS Cloud Project Bootcamp - Dynamic User Handles

AWS Cloud Project Bootcamp - Dynamic User Handles

Since February, I have been busy studying for the AWS Bootcamp. It's been an interesting exercise and I have been using technologies that I normally don't have much exposure to as the Bootcamp is looking at it from the perspective of a Web Developer.

Introduction

The project's end goal is to create a website that is a social media platform that allows users to create short messages called cruds.

The website uses two databases. One is a PostGres database which holds all information related to the user e.g. user information and activities.

User Table Schema

                                   Table "public.users"
     Column      |            Type             | Collation | Nullable |      Default       
-----------------+-----------------------------+-----------+----------+--------------------
 uuid            | uuid                        |           | not null | uuid_generate_v4()
 display_name    | text                        |           | not null | 
 handle          | text                        |           | not null | 
 email           | text                        |           | not null | 
 cognito_user_id | text                        |           |          | 
 bio             | text                        |           |          | 
 created_at      | timestamp without time zone |           | not null | CURRENT_TIMESTAMP
Indexes:
    "users_pkey" PRIMARY KEY, btree (uuid)

Activities Table Schema

                                    Table "public.activities"
         Column         |            Type             | Collation | Nullable |      Default       
------------------------+-----------------------------+-----------+----------+--------------------
 uuid                   | uuid                        |           | not null | uuid_generate_v4()
 user_uuid              | uuid                        |           | not null | 
 message                | text                        |           | not null | 
 replies_count          | integer                     |           |          | 0
 reposts_count          | integer                     |           |          | 0
 likes_count            | integer                     |           |          | 0
 reply_to_activity_uuid | integer                     |           |          | 
 expires_at             | timestamp without time zone |           |          | 
 created_at             | timestamp without time zone |           | not null | CURRENT_TIMESTAMP
Indexes:
    "activities_pkey" PRIMARY KEY, btree (uuid)

We are meant to seed these tables with our users and their information.

The problem

As there could be many different user names and handles The website template uses a standard user "@andrewbrown" in its code for functionality testing. This has been hardcoded in various sections of the website.

This user correlates to the first user in our Postgres database.

The issue is that every boot camper will have different users seeded and not every user will have "@andrewbrown" as the first user in their user's table. This is because the website uses AWS's Cognito authentication system which needs to have an active email address before you can log in so nearly every user's first user will correspond to their own username, handle, and email address.

This causes issues when you log in, try to have conversations with other users on the site and try to perform other activities as the handle "@andrewbrown" does not match up to the currently logged-in user.

For instance, in desktopNavigation.js the profile URL is set as Andrew's. Clicking on the profile link will thus take you to Andrew's profile.

profileLink = <DesktopNavigationLink 
      url="/@andrewbrown" 
      name="Profile"
      handle="profile"
      active={props.active} />

To resolve this various users hardcoded their own username here instead.

profileLink = <DesktopNavigationLink 
      url="/@shehzadashiq" 
      name="Profile"
      handle="profile"
      active={props.active} />

While this works. It will only work for the user who is logged in with that handle. Logging in with the second user in the database e.g. Bayko will still show Andrew's profile.

The Solution

To resolve this issue we need to ensure that the user's handle is set dynamically. Looking at the code in DesktopNavigation.js we can see that the user's information is being passed to the variable profile using ProfileInfo which is defined in ProfileInfo.js

import './DesktopNavigation.css';
import {ReactComponent as Logo} from './svg/logo.svg';
import DesktopNavigationLink from '../components/DesktopNavigationLink';
import CrudButton from '../components/CrudButton';
import ProfileInfo from '../components/ProfileInfo';

export default function DesktopNavigation(props) {

  let button;
  let profile;
  let notificationsLink;
  let messagesLink;
  let profileLink;
  if (props.user) {
    button = <CrudButton setPopped={props.setPopped} />;
    profile = <ProfileInfo user={props.user} />;
    notificationsLink = <DesktopNavigationLink 
      url="/notifications" 
      name="Notifications" 
      handle="notifications" 
      active={props.active} />;
    messagesLink = <DesktopNavigationLink 
      url="/messages"
      name="Messages"
      handle="messages" 
      active={props.active} />
    profileLink = <DesktopNavigationLink 
      url="/@shehzadashiq"
      name="Profile"
      handle="profile"
      active={props.active} />
  }

  return (
    <nav>
      <Logo className='logo' />
      <DesktopNavigationLink url="/" 
        name="Home"
        handle="home"
        active={props.active} />
      {notificationsLink}
      {messagesLink}
      {profileLink}
      <DesktopNavigationLink url="/#" 
        name="More" 
        handle="more"
        active={props.active} />
      {button}
      {profile}
    </nav>
  );
}

Looking at ProfileInfo.js we can see that the user handle is being passed from the properties of the user.

<div className="profile-username">@{props.user.handle || "handle"}</div>

Now we can change the code in the section <profileLink> in DesktopNavigation to use this information. We can do this thus.

    profileLink = <DesktopNavigationLink 
      url={"/@" + props.user.handle}
      name="Profile"
      handle="profile"
      active={props.active} />

This takes the currently logged-in user's information and thus sets the URL for the profile URL dynamically.

We can verify this by logging in as the user "bayko" and then clicking on the Profile link in the sidebar. As expected the URL resolves correctly and loads the profile.

I hope this was useful and allows you to avoid using hardcoded handles in your code now.