Skip to content

Commit

Permalink
Merge pull request #58 from TickLabVN/staging
Browse files Browse the repository at this point in the history
Staging
  • Loading branch information
quannhg authored Dec 7, 2023
2 parents 3c60d21 + 7d697e4 commit 4a1281d
Show file tree
Hide file tree
Showing 33 changed files with 642 additions and 169 deletions.
32 changes: 29 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,8 +1,34 @@
FASTIFY_PORT=
FASTIFY_TEST_PORT=

POSTGRES_USER=
POSTGRES_PASSWORD=
POSTGRES_DB=
POSTGRES_DB=ssps_db
POSTGRES_PORT=
POSTGRES_TEST_PORT=s
POSTGRES_URL=

CORS_WHITE_LIST=
CORS_WHITE_LIST=[http://localhost:3000, http://localhost:8080]
COOKIE_SECRET=
JWT_SECRET=
JWT_SECRET=

MINIO_URL=
MINIO_SERVER_ENDPOINT=
MINIO_PORT=9000
MINIO_ACCESS_KEY=
MINIO_SECRET_KEY=
MINIO_BUCKET_NAME=ssps

CHECKOUT_ENVIRONMENT=sandbox
PAYPAL_LIVE_ENDPOINT=https://api-m.paypal.com
PAYPAL_SANDBOX_ENDPOINT=https://api-m.sandbox.paypal.com
PAYPAL_CLIENT_ID=
PAYPAL_CLIENT_SECRET=

OPEN_EXCHANGE_RATES_ENDPOINT=https://open.er-api.com
OPEN_EXCHANGE_RATES_APP_ID=

GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_REDIRECT_URL=
UI_HOME_URL=https://ssps.tickflow.net/home
4 changes: 4 additions & 0 deletions .github/workflows/dev-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ jobs:
echo MINIO_BUCKET_NAME=${{ secrets.MINIO_BUCKET_NAME }} >> .env
echo >> .env
echo OPEN_EXCHANGE_RATES_ENDPOINT=${{ vars.OPEN_EXCHANGE_RATES_ENDPOINT }} >> .env
echo OPEN_EXCHANGE_RATES_APP_ID=${{ secrets.OPEN_EXCHANGE_RATES_APP_ID }} >> .env
echo >> .env
echo CHECKOUT_ENVIRONMENT=${{ vars.CHECKOUT_ENVIRONMENT }} >> .env
echo PAYPAL_LIVE_ENDPOINT=${{ vars.PAYPAL_LIVE_ENDPOINT }} >> .env
echo PAYPAL_SANDBOX_ENDPOINT=${{ vars.PAYPAL_SANDBOX_ENDPOINT }} >> .env
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/test-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,11 @@ jobs:
echo PAYPAL_SANDBOX_ENDPOINT=${{ vars.PAYPAL_SANDBOX_ENDPOINT }} >> .env
echo PAYPAL_CLIENT_ID=${{ secrets.PAYPAL_CLIENT_ID }} >> .env
echo PAYPAL_CLIENT_SECRET=${{ secrets.PAYPAL_CLIENT_SECRET }} >> .env
echo >> .env
echo >> .env
echo OPEN_EXCHANGE_RATES_ENDPOINT=${{ vars.OPEN_EXCHANGE_RATES_ENDPOINT }} >> .env
echo OPEN_EXCHANGE_RATES_APP_ID=${{ secrets.OPEN_EXCHANGE_RATES_APP_ID }} >> .env
echo >> .env
echo GOOGLE_CLIENT_ID=${{ secrets.GOOGLE_CLIENT_ID }} >> .env
echo GOOGLE_CLIENT_SECRET=${{ secrets.GOOGLE_CLIENT_SECRET }} >> .env
Expand Down
114 changes: 28 additions & 86 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,18 @@
# Fastify Template
# Student Smart Printing Service

[![formatter: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier) [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) ![CI](https://github.com/phucvinh57/fastify-template/actions/workflows/ci.yml/badge.svg) ![Deploy](https://github.com/phucvinh57/fastify-template/actions/workflows/release.yml/badge.svg)

Using [fastify](https://www.fastify.io), this template includes:

- API Docs: `SwaggerUI`
- Input validation: `fluent-json-schema`
- ORM & migration tools: `Prisma`
- Deployment:
- Dockerfile & docker-compose files
- Script CI/CD in `.github/workflows`
- Testing: `jest`
- Code linting & styling: `husky` + `prettier`
- Precommit hook: `lint-staged`

For applying conventional commits, refer [commitizen](https://github.com/commitizen/cz-cli).

## Prerequisites

- `docker` v20.10.22
- `docker-compose` v1.29.2
- `node` v18.13.0
- `npm` 8.19.3
- `cups` 2.4.1
- `cups-pdf` 3.0.1-14 (Virtual printer in case your computer is not connected to any actual printer)

## Commands

Note: Fill in `.env` file (use template from `.env.example`) before starts.

- `yarn bootstrap`: Set up development
- `yarn barrels`: Gather export objects from many files in a folder and re-export in `index.ts` file. See configs in `.barrelsby.json`.
- `yarn start`: Start application in dev mode
Expand Down Expand Up @@ -66,82 +52,38 @@ Note: Fill in `.env` file (use template from `.env.example`) before starts.
┗ 📜index.ts # Program entry
```

## Project configurations

### Code linting & formating

We use [`eslint`](https://eslint.org/) to find and fix problem in code, such as:

- Unused variables
- Use `var` declaration
- Loosely comparation using `==`
- ...

You can run this command to test eslint script:

```bash
yarn lint
```

To maintain only one style coding across members, we use [`prettier`](https://prettier.io/). Try:

```bash
yarn format
```

You don't need to run these scripts regularly or before commiting code. They are run automatically before `git commit` command by setting as a precommit script. In some circumstances, precommit script is not enabled by default, just type two commands below to fix it:
## Setup and Run Instructions

```bash
chmod ug+x .husky/*
chmod ug+x .git/hooks/*
```
### Step 1: Set up Environment Variables
Create a .env file and fill it with the required environment variables. Ensure you replace placeholders like with the actual values.
Note: Fill in `.env` file (use template from `.env.example`) before starts.
For example:

For a tip, two plugins above could be installed in `VSCode`'s extensions.
``` .env
FASTIFY_PORT=3000
FASTIFY_TEST_PORT=3001
### Barrelsby & Path alias
POSTGRES_USER=db_user
POSTGRES_PASSWORD=db_password
POSTGRES_DB=ssps_db
POSTGRES_PORT=5432
POSTGRES_TEST_PORT=5433
POSTGRES_URL=postgresql://db_user:db_password@localhost:5432/ssps_db
```py
............
┣ 📂controllers
┃ ┗ 📜user.ctrler.ts
┣ 📂routes
┃ ┗ 📜user.route.ts
┣ 📂schemas
┃ ┣ 📂in
┃ ┃ ┣ 📜ids.schema.ts
┃ ┃ ┣ 📜user.schema.ts
┃ ┃ ┗ 📜index.ts
............
# ... (Other environment variables)
```

Imagine you are in `user.ctrler.ts` and want to import `ASchema` from `ids.schema.ts`. The code can be like this:

```typescript
import { ASchema } from '../schemas/in/ids.schema.ts'
### Step 2: Run Bootstrap Command
Run the following command to set up the development environment:
```sh
yarn bootstrap
```
This command will likely install dependencies, set up configurations, and perform other necessary tasks.

The more nested folders, the more bad looking importation. It is waste time to guess how many `..` should be put in relative path.

The solution is [`barrelsby`](https://www.npmjs.com/package/barrelsby) and **path alias**. With configurations in `.barrelsby.json`, barrelsby can import your entire code base in a specific folder, and re-export them in `index.ts` file.

Try this:

```bash
yarn barrels
### Step 3: Start the Application
Run the following command to start the application:
```sh
yarn start
```

To avoid using many `..` in relative path, config path alias in `tsconfig.json`. See the guideline [here](https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping).

## Git working culture

- For every updates, DO NOT push directly to `master` branch. Create a new branch, commit, publish branch and create a pull request (PR) instead.
- A branch should have prefix `feat/` for a feature update, prefix `hotf/` for a hotfix, `improv/` for an improvement ...
- A PR should be small enough to review. To split a large PR, use [stacked PRs](https://blog.logrocket.com/using-stacked-pull-requests-in-github/).

## Helpful resources

### Prisma

- [Database schema](https://www.prisma.io/docs/concepts/components/prisma-schema)
- [Type mapping Prisma & PostgreSQL](https://www.prisma.io/docs/concepts/database-connectors/postgresql#type-mapping-between-postgresql-to-prisma-schema)
- [Schema references](https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference)
This command will start your Node.js application. Ensure that ports 5432 and 8080 are available and not in use by other processes.
13 changes: 13 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Security Policy

## Unsupported Security Policy

This project is a PEP (Personal Exercise Project) and does not come with any official support for security updates. As a result, there are no designated versions that are actively supported for security patches.

We acknowledge that security is essential, and users are encouraged to use this project for educational or personal purposes only. Given its nature as a PEP project, there are no guarantees of updates, including security updates.

## Reporting a Vulnerability

While this project does not have a formal process for handling security vulnerabilities, responsible disclosure is appreciated. If you discover a vulnerability and would like to report it, you can do so by creating an issue in the project repository. I will do the best I can to address reported vulnerabilities, but please be aware that there may be no fixed timeline or guarantee of a response.

Users are recommended to use this project responsibly and at their own risk.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
Warnings:
- A unique constraint covering the columns `[previewMinioName]` on the table `File` will be added. If there are existing duplicate values, this will fail.
- Added the required column `previewMinioName` to the `File` table without a default value. This is not possible if the table is not empty.
*/
-- AlterTable
ALTER TABLE "File" ADD COLUMN "previewMinioName" TEXT NOT NULL;

-- CreateIndex
CREATE UNIQUE INDEX "File_previewMinioName_key" ON "File"("previewMinioName");
2 changes: 2 additions & 0 deletions prisma/migrations/20231206165815_/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- DropIndex
DROP INDEX "File_minioName_key";
11 changes: 11 additions & 0 deletions prisma/migrations/20231206170049_/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
Warnings:
- A unique constraint covering the columns `[minioName]` on the table `File` will be added. If there are existing duplicate values, this will fail.
*/
-- DropIndex
DROP INDEX "File_previewMinioName_key";

-- CreateIndex
CREATE UNIQUE INDEX "File_minioName_key" ON "File"("minioName");
2 changes: 2 additions & 0 deletions prisma/migrations/20231206170138_/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "File" ALTER COLUMN "previewMinioName" DROP NOT NULL;
1 change: 1 addition & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ model File {
id String @id @default(cuid())
realName String
minioName String @unique
previewMinioName String?
printingRequest PrintingRequest @relation(fields: [printingRequestId], references: [id])
printingRequestId String
numPage Int @default(0)
Expand Down
5 changes: 4 additions & 1 deletion prisma/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,12 @@ const createConfiguration = async () => {
}[] = [
{ name: 'coin per page', value: '2', description: 'The amount of coin a student needs to print one page' },
{ name: 'dollar to coin', value: '73', description: 'The amount of coin user gets per dollar' },
{ name: 'coin to vnd', value: '200', description: 'The value of one coin exchange to vnd' },
{ name: 'bonus coin per 100000 vnd', value: '20', description: 'The amount of coin is bonus for 100 000 vnd' },
{ name: 'coin per sem', value: '100', description: 'The amount of coin a student has free in one semester' },
///100mb = 100 * 1024 * 1024 (byte)
{ name: 'max file size', value: `${100 * 1024 * 1024}`, description: 'The amount of coin a student has free in one semester' }
{ name: 'max file size', value: `${100 * 1024 * 1024}`, description: 'The amount of coin a student has free in one semester' },
{ name: 'service fee', value: `5`, description: 'The amount of coin for a printing request be executed' }
];

const serializedExtensions = JSON.stringify(acceptedExtensions);
Expand Down
2 changes: 2 additions & 0 deletions src/configs/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export const envs = cleanEnv(process.env, {
PAYPAL_SANDBOX_ENDPOINT: url(),
PAYPAL_CLIENT_ID: str(),
PAYPAL_CLIENT_SECRET: str(),
OPEN_EXCHANGE_RATES_ENDPOINT: url(),
OPEN_EXCHANGE_RATES_APP_ID: str(),
GOOGLE_CLIENT_ID: str({ default: 'anc' }),
GOOGLE_CLIENT_SECRET: str(),
GOOGLE_REDIRECT_URL: url(),
Expand Down
1 change: 1 addition & 0 deletions src/constants/PrintingRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ export const DEFAULT_ACCEPTED_EXTENSION = ['pdf'];
export const DEFAULT_COIN_PER_PAGE = 2;
export const DEFAULT_COIN_PER_SEM = 100;
export const DEFAULT_MAX_FILE_SIZE = 100 * 1024 * 1024;
export const DEFAULT_SERVICE_FEE = 5;
2 changes: 2 additions & 0 deletions src/constants/coin.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export const DEFAULT_DOLLAR_TO_COIN = 73;
export const DEFAULT_COIN_TO_VND = 200;
export const DEFAULT_BONUS_COIN_PER_100000_VND = 20;
14 changes: 14 additions & 0 deletions src/dtos/out/configuration/acceptedExtension.dto.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
import { Static, Type } from '@sinclair/typebox';

export const AcceptedExtensionDto = Type.Array(Type.String());
export const ServiceFeeDto = Type.Number();
export const CoinPerPageDto = Type.Number();
export const CoinPerSemDto = Type.Number();
export const DollarToCoinDto = Type.Number();
export const BonusCoinPer100000VndDto = Type.Number();
export const CoinToVNDDto = Type.Number();
export const MaxFileSizeDto = Type.Number();

export type AcceptedExtensionDto = Static<typeof AcceptedExtensionDto>;
export type ServiceFeeDto = Static<typeof ServiceFeeDto>;
export type CoinPerPageDto = Static<typeof CoinPerPageDto>;
export type CoinPerSemDto = Static<typeof CoinPerSemDto>;
export type DollarToCoinDto = Static<typeof DollarToCoinDto>;
export type CoinToVNDDto = Static<typeof CoinToVNDDto>;
export type BonusCoinPer100000VndDto = Static<typeof BonusCoinPer100000VndDto>;
export type MaxFileSizeDto = Static<typeof MaxFileSizeDto>;
3 changes: 2 additions & 1 deletion src/dtos/out/configuration/configuration.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { Static, Type } from '@sinclair/typebox';
export const ConfigurationDto = Type.Array(
Type.Object({
name: Type.String(),
value: Type.String()
value: Type.String(),
description: Type.String()
})
);

Expand Down
3 changes: 2 additions & 1 deletion src/dtos/out/printing/printFile.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { Static, Type } from '@sinclair/typebox';

export const PrintingFileResultDto = Type.Object({
status: Type.String(),
message: Type.String()
message: Type.String(),
printingRequestId: Type.String()
});

export type PrintingFileResultDto = Static<typeof PrintingFileResultDto>;
9 changes: 6 additions & 3 deletions src/dtos/out/printing/printingRequest.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ export const GetPrintingRequestResultDto = Type.Array(
filesName: Type.Array(Type.String({ format: 'fileName' })),
numPages: Type.Number({ format: 'pageNumber' }),
coins: Type.Number({ format: 'coins' }),
paid: Type.String({ format: 'paid' })
paid: Type.String({ format: 'paid' }),
serviceFee: Type.Number()
})
);

Expand Down Expand Up @@ -38,11 +39,13 @@ export const DeleteFilePrintingRequestResultDto = Type.Object({
});

export const ExecutePrintingRequestResultDto = Type.Object({
PrintingStatus: Type.Enum(PRINTING_STATUS)
PrintingStatus: Type.Enum(PRINTING_STATUS),
printingRequestId: Type.String()
});

export const CancelPrintingRequestResultDto = Type.Object({
printingStatus: Type.Enum(PRINTING_STATUS)
printingStatus: Type.Enum(PRINTING_STATUS),
printingRequestId: Type.String()
});

export type GetPrintingRequestResultDto = Static<typeof GetPrintingRequestResultDto>;
Expand Down
6 changes: 4 additions & 2 deletions src/dtos/out/printing/uploadFile.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ export const UploadFileResultDto = Type.Object({
});

export const UploadConfigResultDto = Type.Object({
status: Type.String()
status: Type.String(),
fileId: Type.String()
});

export const FilePrintNumberChangeRequestResultDto = Type.Object({
status: Type.String(),
message: Type.Optional(Type.String())
message: Type.Optional(Type.String()),
fileId: Type.Optional(Type.String())
});

export type UploadFileResultDto = Static<typeof UploadFileResultDto>;
Expand Down
Loading

0 comments on commit 4a1281d

Please sign in to comment.