Registering the User - Planning

Refer back to Chapter 6, The Bookstore API Endpoint Specifications, API Endpoint #1: User Registration section for the API endpoint specifications.

1 - Route Name

Following the guidelines in chapter 6, Method Verbs and URI Design, we will create the following URI. Since it is a resource creation, using POST over any other method verbs would make sense here.

As for the namespace, we will follow Guideline #4: Avoid actions and verbs in the URI in chapter 3, URI Design, URI Path Design. This means we should not use any verbs, but rather let the POST method verb speak for itself on what resource it will create. A lot of developers will make the mistake of making the URI something like this /api/v1/auth/regster or /api/v1/users/create. Don't do this as it is the exact opposite of the guideline we are trying to follow.

Also, don't forget to always pluralize the resources your endpoints. In our case, the resource being users.

The following URI is what we will be going with.

POST /api/v1/users

2 - Input Request

As stated from the endpoint specifications in the previous chapter, we will accept the following input fields from the client.

  • first_name

  • last_name

  • email

  • password

  • password_confirmation

  • phone_number

3 - Middleware

Since this is a going to be a public user registering for an account, no middleware is necessary.

However, since this chapter has a bunch of input validation, we'll be adding in a global middleware that will catch and handle all exceptions in our application. You will see more of this in the next section.

4 - Validation

From the looks of the specification, it would seem like we'll need to perform the following validation rules for each of the fields.

  • first_name - required.

  • last_name - required.

  • email - required, must be a valid email format.

  • password - required, at least 6 characters.

  • password_confirmation - required, password and password_confirmation must match.

  • phone_number - required, must be a valid phone number format.

5 - Domain

From the specifications, it looks like we will need the following user entity in our domain layer.

userModel

  • first_name

  • last_name

  • email

  • password

  • phone_number

We will also need some sort of way to make a query to the database to insert the user in, so we'll create a userRepository layer with the method createUser() to do so.

userRepository

  • createUser()

On top of that, our controller will call a service to registerUser(), in this case, it will be the authService which will use the userRepository layer. We'll also need to keep in mind that we will have to do some sort of database validation here since there can only be one unique email in the users table.

authService

  • registerUser()

This is a rough outline of how we are going to be implementing these functions, we'll take a deeper dive at the implementations in the next section of this chapter.

*Note: for the purposes of demonstration in this book, we will not be hashing our passwords. If you want to deploy any sort of authentication system into production, always remember to hash your passwords.

6 - Events

Send an email to the registered user's email letting them know that they have successfully registered.

7 - Response

There are 4 possible responses we could possibly return from this endpoint.

The first is a successful response in which we have successfully inserted the newly registered user into the database and fired off an email to that user.

{
    "status": "success",
    "code": 201,
    "message": "User has successfully been registered."
    "data": {
        "id": "61f889bbc6bbf81a97ba69d6",
        "first_name": "John",
        "last_name": "Doe",
        "email": "johndoe@email.com",
        "phone_number": "1234567890"
    },
    "errors": null
}

The second would be an error on an invalid input request payload.

{
  "status": "error",
  "code": 422,
  "message": "Input fields are of not the correct form.",
  "data": null,
  "errors": [
    "This DTO's property is required: email.",
    "This DTO's property is required: password.",
    "This DTO's property is required: password_confirmation.",
    "This DTO's property is required: phone_number."
  ]
}

*Note: I won't be mentioning any more DTO validations in the ensuing chapters as the response is quite routine for most API calls with an input request body. So for login user, create a book, and update a book API endpoints, it's implied that a DTO will yield a particular response depending on the input from the client.

The third would be an error on the form validation.

{
  "status": "error",
  "code": 400,
  "message": "There were errors with the validation.",
  "data": null,
  "errors": [
    "The email format is invalid.",
    "The password confirmation and password fields must match."
  ]
}

Lastly, the fourth would be a backend database validation checking if an email address is already taken.

{
  "status": "error",
  "code": 409,
  "message": "This email is already taken.",
  "data": null,
  "errors": ["This email is already taken."]
}

Last updated