Skip to content

Latest commit

 

History

History
274 lines (229 loc) · 7.3 KB

README.md

File metadata and controls

274 lines (229 loc) · 7.3 KB

Money Forward interview

Requirements

The server api should serve for this endpoints:

  • GET /users/{id}
  • GET /users/{id}/accounts
  • GET /accounts/{id}

All endpoints should return json payloads matching the following criteria. /users/{id}: A detail of users including list account_ids that have been owned by the user that are equal to the passing {id} from the database.

Example:

{
  "id": 1,
  "name": "Alice",
  "account_ids": [
    1,
    3,
    5,
    ...
  ]
}

/users/{id}/accounts: A list detail of accounts that have been owned by the user that are equal to the passing {id} from the database.

Example:

[
  {
    "id": 1,
    "user_id": 1,
    "name": "A銀行",
    "balance": 20000
  },
  {
    "id": 3,
    "user_id": 1,
    "name": "C信用金庫",
    "balance": 120000
  },
  {
    "id": 5,
    "user_id": 1,
    "name": "E銀行",
    "balance": 5000
  },
  ...
]

/accounts/{id}: A detail of accounts that are equal to the passing {id} from the database.

Example:

{
  "id": 2,
  "user_id": 2,
  "name": "Bカード",
  "balance": 200
}

Features (the APIs that not occurs in requirements):

  • Finish three APIs in Requirements.
  • Adding mutation APIs for accounts, users.
  • Adding login flow.
  • Apply caching for optimize API.
  • Adding some middlewares hor http handle steps like recovery,cors,authenticate,rbac.

Architecture:

The Architecture using the clean architecture that control the system split to 3 layers.

clean architecture

Built With

This section list any major frameworks/libraries used to bootstrap project.

  • Go
  • Postgres

Libraries:

  • Using snowflake engine for generate id.
  • Using paseto engine for generate token.
  • Using lru for in memory caching.
  • Using pq for postgres driver.
  • Using cobra for generate command line.

Folder structure

.
├── LICENSE
├── Makefile   #for quickly command line
├── README.md
├── app-exe     # binary of go build
├── cmd         # contain command line for running
│   ├── root.go
│   ├── srv.go
│   └── start.go
├── configs       # contain config object and environment loader
│   ├── address.go
│   ├── configs.go
│   └── database.go
├── deployments   # using for deployments
├── developments  # using for developments include docker, env file
│   ├── dev.env     # environment file for dev environment
│   └── docker-compose.yml   # docker compose file for dev environment
├── go.mod
├── go.sum
├── internal  # contain layers that applying clean architecture without export to outside this module.
│   ├── deliveries # contain delivery/transport layer of clean architecture
│   │   └── http
│   │       ├── account.go
│   │       ├── auth.go
│   │       └── user.go
│   ├── entities # contain entities (data transfer object)
│   │   ├── account.go
│   │   └── user.go
│   ├── models # contain models that including request, response.
│   │   ├── account.go
│   │   ├── auth.go
│   │   ├── common.go
│   │   └── user.go
│   ├── repositories # contain repository/store layer of clean architecture
│   │   ├── account.go
│   │   └── user.go
│   └── services # contain service/domain layer of clean architecture
│       ├── account.go
│       ├── auth.go
│       └── user.go
├── main.go
├── migrations # contain migration files for database
│   ├── 00001_migrate.up.sql
│   └── 00002_migrate.up.sql
└── pkg    
    ├── cache # contain interface of cache pattern
    │   └── cache.go
    ├── crypto_utils # contain password util 
    │   └── util.go
    ├── database # contain database util
    │   ├── executor.go
    │   ├── type.go
    │   └── util.go
    ├── http_server # contain http server that follow native http lib by go
    │   ├── common.go
    │   ├── http.go
    │   ├── http_test.go
    │   ├── middleware.go
    │   ├── response.go
    │   ├── util.go
    │   ├── util_test.go
    │   └── xcontext  # contain context of http handler
    │       ├── context.go
    │       └── ctx.go
    ├── id_utils  # for id utility
    │   ├── id.go
    │   └── snowflake.go  # snowflake id generator
    ├── logger  # for logger
    │   └── logger.go
    ├── lru # for lru cache
    │   └── cache.go
    ├── postgres_client # postgres client
    │   ├── client.go
    │   └── tx.go
    ├── processor
    │   └── processor.go
    ├── reflect_utils # contain reflect utility
    │   ├── util.go
    │   └── util_test.go
    └── token_utils    # contain token utility
        ├── authenticator.go
        ├── jwt.go
        └── paseto.go

Prerequisites

  • Make sure you have Go installed (download). Version 1.21 or higher is required.
  • Docker (version 20.10.22+)

Getting started

First of all, we should set up environments:

  copy ./developments/.env.example ./developments/.env
  copy ./developments/dev.env.example ./developments/dev.env
  1. Starting database:
  make start-db
  1. Migrate:
  make migrate
  1. Simple start server:
  make start

Action flows:

We already migrate a default super admin user by admin and donkihote.

  curl --location 'localhost:8080/auth/login' \
    --header 'Content-Type: application/json' \
    --data '{
        "user_name":"admin",
        "password": "donkihote"
    }'

Create user:

  curl --location 'localhost:8080/users' \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Bearer ${given_token}' \
    --data '{
        "name": "Le Duy Dat",
        "user_name": "duyledat197",
        "password": "1234567",
        "role": "USER"
    }'

Get user detail (include account ids) by id:

curl --location 'localhost:8080/users/{id}' \
  --header 'Content-Type: application/json'

Create account by user id:

  curl --location 'localhost:8080/users/{id}/accounts' \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Bearer ${given_token}' \
    --data '{
      "name": "Account 1",
      "balance": 100
    }'

Get accounts by user id:

curl --location 'localhost:8080/users/{id}/accounts' \
  --header 'Content-Type: application/json'

Get account detail by id:

curl --location 'localhost:8080/accounts/{id}' \
  --header 'Content-Type: application/json'