Creating a Reddit Clone Using React and GraphQL - 10
Tags: react, typescript, graphql, redditclone
Published: 2021-03-04 16:55:39

#### This post originally posted on [my blog site](https://www.rasikag.com/posts/learning-react-with-ben-awad-10).

Now we are adding email functions to the server. For this, we use `NodeMailer`. Use the below command to add it.

```javascript

yarn add nodemailer
yarn add -D @types/nodemailer // this is for TS support

```

We can grab the code from there example and paste it into a file. Now we are creating `forgotPassword` mutation. Before that, we need to add the email field to `User` entity.

```javascript

@Field()
@Property({ type: "text", unique: true })
email!: string;

```

Then we need to run the migration command to update the database. Then once we run the application we will get this error.

```javascript

alter table "user" add column "email" text not null;

```

This is because we are trying to add a not null column, but we have some users without an email address. For now, let’s delete all users.

Now we need to update user registration mutation because now email is a mandatory field. Add it to query builder also.

Now we are changing login mutation to match with this new change.

First, change in `fineOne` method that checks does the user passed `username` or `email`.

```javascript
const user = await em.findOne(
  User,
  usernameOrEmail.includes("@")
    ? { email: usernameOrEmail }
    : { username: usernameOrEmail }
);
```

Now there is a scenario that user can have `@` in there username. Let’s handle that. With that validation, we create a separate `util` file called `validateRegister` . Then use that util function in `register` mutation.

```javascript
...
const errors = validateRegister(options);
if (errors) {
  return {errors};
}
...

```

Here you will see that we are returning the error `array` as an object. The returned object is matching with the return type.

Let’s change the front-end code to match with this back-end code.

We change the Login `graphql` query to get the `usernameOrEmail` first.

```javascript

mutation Login($usernameOrEmail: String!, $password: String!) {
  login(usernameOrEmail: $usernameOrEmail, password: $password) {
... // rest of code is same

```

Then change the Register `graphql` query.

```javascript

mutation Register($options: UsernamePasswordInput!) {
register(options: $options){
... //rest of code is same

```

Then add the `email` input field in to `Register.tsx` page.

After all these changes we are coming back to send emails for users that forgot password.

In the `user.ts` file inside the resolvers folder, we are adding `forgotPassword` mutation.

```javascript

@Mutation(() => Boolean)
async forgotPassword(
  @Arg("email") email: string,
  @Ctx() { em }: RedditDbContext
) {
  const user = await em.findOne(User, {email});
  if (!user) {
    return true;
  }
  const token = "asdasdsadassadsadsadsadsad";
  await sendEmail(email,
    '<a href="http://localhost:3001/reset-password/${token}">click here to reset password</a>');

  return true;

}

```

Within there, we first check that user email exists, if so we create a token and attached it to the reset-password link. We use `uuid` package for creating a unique user token to attach to the URL.

```javascript

yarn add uuid ioredis

```

Also, install the type support to it.

```javascript

yarn add -D @types/uuid @types/ioredis

```

Now we use `ioredis` and let’s make relevant changes in the `index.ts` file.

Also, we are passing `redis` in to context that later we can use it in the resolver. So now we need to add that to `RedditDbContext` type.

Then create a `Redis` object and use it in the `RedisStore` .

```javascript

// inside the index.ts file
const redis = new Redis();
// use this redis object inside the RedisStore
...
store: new RedisStore({ client: redis, disableTouch: true }),
...

```

Then inside the `forgotPassword` mutation use this redis object. There are a few things happening here.

First, we create a toke using `uuid`. Then we store this in `Redis`. After that, we set this token in the URL.

```javascript
const token = v4();
await redis.set(
  FORGET_PASSWORD_PREFIX + token,
  user.id,
  "ex",
  1000 * 60 * 60 * 24 * 3
);
```

---

I will wrap up this post from here. If you have anything to ask regarding this please leave a comment here. Also, I wrote this according to my understanding. So if any point is wrong, don’t hesitate to correct me. I really appreciate you.
That’s for today friends. See you soon. Thank you.

**References:**

This article series based on the [Ben Award - Fullstack React GraphQL TypeScript Tutorial](https://www.youtube.com/watch?v=I6ypD7qv3Z8). This is an amazing tutorial and I highly recommend you to check that out.

Main image [credit](https://www.pexels.com/photo/landscape-photography-of-brown-mountains-surrounding-lake-620337/)