/passbook-app-backend

contains backend api code for passbook app

Primary LanguageGo

23-03-2024

Passbook App API

API using golang for the passbook app frontend

click here for entity and functional requirement list.

base URL: http://api.domain.app/v1/

Docker steps

To run the app in docker container follow the steps below:

  1. Build the docker image using multistage dockerfile that will build the go binary and then copy it to a smaller image for running the app.
docker build -t passbook-app-backend -f Dockerfile.multistage . 
  1. Run the image in a docker container and pass the .env file as an environment file.
docker run -p 8080:8080 -d --env-file dev.env passbook-app-backend

To view the logs of the running container use the command below:

docker logs -f <container_name>

Local run without docker

To run the app locally without docker you need to set PASSBOOK_ENV=DEV so that the code reads the dev.env file for environment variables.

PASSBOOK_ENV=DEV CGO_ENABLED=0 go run cmd/passbook-app/main.go

All above commands are also present in the makefile. You can run the commands using make command.

Authentication

Authorization: Bearer <token>

Generic Responses

Success Response

{
    "status": "success",
    "message": "success message",
    "data": {},
    "meta": {
        "total_pages": 100,
        "page": 1,
        "limit": 10
    }
}

Error Response

{
    "status": "error",
    "message": "error message",
    "data": {},
    "meta": {}
}

Auth Endpoints

POST /auth/register - Register User

Request

{
    "username": "john_doe",
    "email": "john.doe@email.com",
    "password": "password"
}

Responses

  • 201: User created successfully
{
    "status": "success",
    "message": "User created successfully",
    "data": {
        "username": "john_doe",
        "email": "john_doe@email.com"
    }
}
  • 400: Validation error
  • 409: User already exists
  • 500: Internal failures

POST /auth/login - Login User

Request

{
    "username": "john.doe",
    "password": "password"
}

Responses

  • 401: Unauthorized
  • 200: User logged in successfully
{
    "status": "success",
    "message": "User logged in successfully",
    "data":{
        "access_token": "jwt_token",
        "user": {
            "username": "john_doe",
            "email": "john.doe@email.com"
        }
    }
}

Use access_token in Authorization header for further requests. The refresh_token is part of a secure httpOnly cookie sent by the server. Both tokens are jwt tokens. The access_token is short-lived (15 minutes) and the refresh_token is long-lived (24 hours).

jwt token payload

{
  "userId": "a7437e4e-a898-4c17-b96e-acf32754ae6e", // uuid
  "exp": 1711901181,// expiry time
  "iat": 1711814781 // issued at
}

POST /auth/refresh - Refresh access token

Expected to be called when the access token is expired. The refresh should be present in the http-only cookie of the request headers.

Responses

  • 400: Bad request (missing refresh token in cookie)
  • 401: Unauthorized (invalid refresh token)
  • 500: Internal failures
  • 200: Access token refreshed successfully
{
    "status": "success",
    "message": "Token refreshed successfully",
    "data": {
        "access_token": "jwt_token"
    }
}

Also as part of token rotation strategy, the server will send a new refresh token in the http-only cookie. For more info on how refresh tokens work I would suggest reading this article by Auth0 team.

User Endpoints

All endpoints marked with the 🔒 symbol require you to pass the access_token as a Bearer token in Authorization header.

GET /users/me 🔒 - Get User Profile

curl -X GET http://api.domain.app/v1/users/me -H "Authorization : Bearer <token>"

Passbook Endpoints

POST /passbooks 🔒 - Create Passbook

Request

{
    "bank_name": "Bank of Zelda",
    "account_number": "123512",
    "total_balance": 1024.45,
    "nickname": "salary"
}

Responses

  • 201: Passbook created successfully
{
    "data": {
        "passbook": {
            "passbook_id": "217c0dc1-cd9a-4562-825c-376b0da8a96e",
            "user_id": "3aaff7dd-91f3-4eab-8b26-b4ddbe68e5a5",
            "bank_name": "Bank of Zelda",
            "account_number": "123512",
            "total_balance": 1024.45,
            "nickname": "salary",
            "created_at": "2024-04-02T00:22:09.134347+05:30",
            "updated_at": "2024-04-02T00:22:09.134347+05:30"
        }
    },
    "status": "success"
}
  • 400: Validation errors or account already exists
  • 500: Internal failures

GET /passbooks 🔒 - Get All Passbooks created by logged in user

Responses

  • 200: Passbooks fetched successfully
{
    "data": {
        "passbooks": [
            {
                "passbook_id": "217c0dc1-cd9a-4562-825c-376b0da8a96e",
                "user_id": "3aaff7dd-91f3-4eab-8b26-b4ddbe68e5a5",
                "bank_name": "Bank of Zelda",
                "account_number": "123512",
                "total_balance": 1024.45,
                "nickname": "salary",
                "created_at": "2024-04-02T00:22:09.134347+05:30",
                "updated_at": "2024-04-02T00:22:09.134347+05:30"
            },
            {
                "passbook_id": "2aaff5dd-61f3-4eab-8b26-b4ddbe68e5a5",
                "user_id": "3aaff7dd-91f3-4eab-8b26-b4ddbe68e5a5",
                "bank_name": "Bowser Bank",
                "account_number": "900000123512",
                "total_balance": 1221024.45,
                "nickname": "savings",
                "created_at": "2024-04-02T00:22:09.134347+05:30",
                "updated_at": "2024-04-02T00:22:09.134347+05:30"
            }
        ]
    },
    "status": "success"
}

GET /passbooks/:passbook_id 🔒 - Get Passbook

Responses

  • 200: Passbook fetched successfully
{
    "data": {
        "passbook": {
            "passbook_id": "217c0dc1-cd9a-4562-825c-376b0da8a96e",
            "user_id": "3aaff7dd-91f3-4eab-8b26-b4ddbe68e5a5",
            "bank_name": "Bank of Zelda",
            "account_number": "123512",
            "total_balance": 1024.45,
            "nickname": "salary",
            "created_at": "2024-04-02T00:22:09.134347+05:30",
            "updated_at": "2024-04-02T00:22:09.134347+05:30"
        }
    },
    "status": "success"
}
  • 404: Passbook not found
  • 500: Internal failures

DELETE /passbooks/:passbook_id 🔒 - Delete Passbook

Responses

  • 404: Passbook not found
  • 200: Passbook deleted successfully
{
    "status": "success",
    "message": "Passbook deleted successfully"
}

PATCH /passbooks/:passbook_id 🔒 - Update Passbook

Request

{
    "passbook_id": "217c0dc1-cd9a-4562-825c-376b0da8a96e",
    "user_id": "3aaff7dd-91f3-4eab-8b26-b4ddbe68e5a5",
    "bank_name": "Bank of Zelda",
    "account_number": "123512",
    "total_balance": 2024.45,
    "nickname": "salary old"
}

Responses

  • 200: Passbook updated successfully
{
    "passbook_id": "217c0dc1-cd9a-4562-825c-376b0da8a96e",
    "user_id": "3aaff7dd-91f3-4eab-8b26-b4ddbe68e5a5",
    "bank_name": "Bank of Zelda",
    "account_number": "123512",
    "total_balance": 2024.45,
    "nickname": "salary old",
    "created_at": "2024-04-02T00:22:09.134347+05:30",
    "updated_at": "2024-05-22T01:02:09.134347+05:30"
}
  • 404: Passbook not found
  • 403: Forbidden if user_id on reqeust body and token user_id do not match
  • 500: Internal failures

Transaction Endpoints

GET /passbooks/:passbook_id/transactions 🔒 - Get All Transactions paginated

  • Query params
    • page: 1
    • limit: 10
    • party_name: "Aditya Gupta"
    • tags: "fun,dividend"
    • type: "CREDIT"

Responses

  • 200: Transactions fetched successfully
{
    "status": "success",
    "code": 200,
    "message": "Transactions fetched successfully",
    "data": [
        {
            "amount": 1500.00,
            "transaction_date": "2023-12-31T14:48:00.000Z",
            "type": "CREDIT",
            "party_name": "Aditya Gupta",
            "description": "ice cream contribution",
            "tags": "vacation,food,fun"
        },
        {
            "amount": 2000.00,
            "transaction_date": "2023-12-31T15:48:00.000Z",
            "type": "DEBIT",
            "party_name": "TCS",
            "description": "dividend from stocks",
            "tags": "stocks,dividend"
        }
    ],
    "meta": {
        "total_pages": 100,
        "page": 1,
        "limit": 10
    }
}

POST /passbooks/:passbook_id/transactions 🔒 - Add Transaction

Request

{
    "amount": 1500.00,
    "transaction_date": "2023-12-31T14:48:00.000Z",
    "type": "CREDIT",
    "party_name": "Aditya Gupta",
    "description": "ice cream contribution",
    "tags": "vacation,food,fun",
}

Responses

  • 201: Transaction added successfully
  • 400: Validation error

GET /passbooks/:passbook_id/transactions/:transaction_id 🔒 - Get Transaction

PATCH /passbooks/:passbook_id/transactions/:transaction_id 🔒 - Update Transaction