Thinh's ShopBack Node.js Challenge

FEATURES

Required Features:

  1. Allow users to register a new account with name, email and password.
  2. Account login by email and password.
    • Request should have a parameter to specify device info: X-Device: mobile / web_browser.
    • Request should have a parameter to support language: X-Language: en / vi.
    • Response: Contains a uuid in response header, for successful login.
    • uuid is an OTP, which will be used once for every request, expires after 2 hours and users need to login again to refresh.
  3. Logout, the OTP will be expired immediately.
  4. Search by email, name, latest access and supports pagination.

Security and assumptions:

  • All passwords are encrypted with bcrypt, 7 rounds by default.
  • Each OTP generated is available for ONE request only.
  • OTP comes with the device you use to sign in. Mobile OTP cannot be used to authenticate requests from web_browser.

INSTALLATION

  1. Make sure you have the latest LTS version of Node.js (download here).
  2. cd to root directory (the one with index.js). Install dependencies by running npm install.

START SERVER

Dev

  1. Start the live server by PORT=8080 npm start.

Production build & Start server

  1. Build the production code by npm run build.
  2. Start the server by PORT=8080 npm run start-build.

SAMPLE DATA

Admin account

{
    "email": "[email protected]",
    "password": "12345678"
}

API SPECIFICATIONS

Sign Up

Request

POST /api/signup

X-Language: en / vi
X-Device: mobile / web_browser
Content-Type: application/json

{
    "email": "[email protected]",
    "password": "12345678",
    "name": "Thinh Nguyen"
}

Responses

  • 201 Created: User created successfully
(For X-Device: mobile and X-Language: vi)
{
    "success": true,
    "code": 201,
    "message": "Bạn đã được đăng kí thành công",
    "data": [
        {
            "email": "[email protected]",
            "fullname": "Thinh Nguyen",
            "latest": null,
            "created": 1602009470
        }
    ]
}

(For X-Device: web_browser and X-Language: vi)
{
    "success": true,
    "code": 201,
    "message": "Bạn đã được đăng kí thành công",
    "data": [
        {
            "login_id": "[email protected]",
            "full_name": "Thinh Nguyen",
            "latest_login": null,
            "created_date": "2020-10-06T19:08:22.239Z"
        }
    ]
}
  • 400 Bad Request: User data is invalid
{
    "success": true,
    "code": 400,
    "message": "The data you sent is invalid. Please check and try again",
    "data": [
        {
            "msg": "Invalid value",
            "param": "name",
            "location": "body"
        }
    ]
}
  • 409 Conflict: Email has been registered
{
    "success": true,
    "code": 409,
    "message": "This email is already registered in the system. Please try another one"
}
  • 500 Internal Server Error

Sign In

Request

POST /api/signin

X-Language: en / vi
X-Device: mobile / web_browser
Content-Type: application/json

{
    "email": "[email protected]",
    "password": "12345678"
}

Responses

  • 200 OK: User logged in successfully
Response headers:
- uuid: 097fcd6c-1933-4b03-b148-4000f6d1b4d1

(For X-Device: mobile and X-Language: vi)
{
    "success": true,
    "code": 200,
    "message": "Bạn đã đăng nhập thành công",
    "data": [
        {
            "email": "[email protected]",
            "fullname": "Thinh Nguyen",
            "latest": 1602011887,
            "created": 1602011883
        }
    ]
}

(For X-Device: web_browser and X-Language: vi)
{
    "success": true,
    "code": 200,
    "message": "Bạn đã đăng nhập thành công",
    "data": [
        {
            "login_id": "[email protected]",
            "full_name": "Thinh Nguyen",
            "latest_login": "2020-10-06T19:18:33.163Z",
            "created_date": "2020-10-06T19:18:03.836Z"
        }
    ]
}
  • 400 Bad Request: Credentials is invalid
{
    "success": true,
    "code": 400,
    "message": "The data you sent is invalid. Please check and try again",
    "data": [
        {
            "msg": "Invalid value",
            "param": "password",
            "location": "body"
        }
    ]
}
  • 500 Internal Server Error

Search users

Request

GET /api/user/search
     ?page=(int, optional, default: 10)
     &items_per_page=(int, optional, default: 30)
     &name=(str, optional, example: thinh)
     &email=(str, optional, example: [email protected])
     &last_accessed_from=(str, optional, datetime, example: 2020-10-04)
     &last_accessed_to=(str, optional, datetime, example: 2020-10-08)
(Parameters are all optional)

For example:
/user/search?name=thinh&items_per_page=2&page=1&last_accessed_from=2020-09-05&last_accessed_to=2020-09-08

X-Language: en / vi
X-Device: mobile / web_browser
Content-Type: application/json
uuid: 097fcd6c-1933-4b03-b148-4000f6d1b4d1

Responses

  • 200 OK: Matching users found
(For X-Device: mobile and X-Language: vi)
{
    "success": true,
    "code": 200,
    "message": "Truy vấn dữ liệu thành công",
    "data": {
        "total_pages": 1,
        "total_items": 2,
        "items_per_page": 30,
        "items": [
            {
                "email": "[email protected]",
                "fullname": "Thinh Nguyen",
                "latest": 1602009484,
                "created": 1602006074
            },
            {
                "email": "[email protected]",
                "fullname": "Thinh Nguyen",
                "latest": 1602012463,
                "created": 1602011883
            }
        ]
    }
}

(For X-Device: web_browser and X-Language: vi)
{
    "success": true,
    "code": 200,
    "message": "Truy vấn dữ liệu thành công",
    "data": {
        "total_pages": 1,
        "total_items": 2,
        "items_per_page": 30,
        "items": [
            {
                "login_id": "[email protected]",
                "full_name": "Thinh Nguyen",
                "latest_login": "2020-10-06T18:38:04.875Z",
                "created_date": "2020-10-06T17:41:14.302Z"
            },
            {
                "login_id": "[email protected]",
                "full_name": "Thinh Nguyen",
                "latest_login": "2020-10-06T19:27:43.776Z",
                "created_date": "2020-10-06T19:18:03.836Z"
            }
        ]
    }
}
  • 400 Bad Request: Filters or pagination query strings are invalid
{
    "success": true,
    "code": 400,
    "message": "The data you sent is invalid. Please check and try again",
    "data": [
        {
            "value": "hello",
            "msg": "Invalid value",
            "param": "items_per_page",
            "location": "query"
        }
    ]
}
  • 403 Forbidden: An user trying to access an admin-only endpoint
{
    "success": true,
    "code": 403,
    "message": "You don't have the permission to perform this action"
}
  • 500 Internal Server Error