Code Monkey home page Code Monkey logo

api's Introduction

Дарителска Платформа Подкрепи.бг
REST API

Podkrepi.bg logo

API tests Deployment

Links

Service Development Staging Production
Website https://localhost:3040 https://dev.podkrepi.bg https://podkrepi.bg
Rest API https://localhost:5010/api/v1 https://dev.podkrepi.bg/api/v1 https://podkrepi.bg/api/v1
Swagger https://localhost:5010/swagger https://dev.podkrepi.bg/swagger https://podkrepi.bg/swagger

Dependencies and References

Setup Development Environment (recommended)

To run and develop the module NodeJS 20 is required. In this section 2 ways of configuring a development environment are described.

Installing the prerequisites

The following prerequisites are required in order to be able to run the project:

Development container

If you wish to keep your host clean, it is also possible to develop the module in a Docker container. You can do that by using the Visual Studio Code's Remote Containers extension and read how to initialize your dev container.

  • Make sure you have the extension installed
  • Open the folder of the module in VS Code
  • Hit Ctrl/Cmd + Shift + P -> Remote-Containers: Reopen Folder in Container

Clone the code and install dependencies

git clone [email protected]:podkrepi-bg/api.git
cd api

yarn set version berry
yarn

Create Docker containers for the Dev Database(postgres) and the Identity Server(Keycloak)

Run the below command in your terminal:

docker compose up -d pg-db keycloak

This will start the following services in your local docker:

Initialize the Database with Prisma Migration scripts

This is needed first time only. We use Prisma as Database management and versioning tool the following migration command will init the database from the schema.prisma file. See Database Development Guidelines below for further details.

# Create db schema
yarn prisma migrate deploy

# Generate the prisma clients
yarn prisma generate

# Seed initial test data
yarn prisma db seed

Setup local environment

Copy the provided .env.example to .env

cp .env.example .env

Note: To avoid modifying the original file, you can create .env.local and add overrides for the variables that are specific to your local environment. This approach allows you to keep your customizations separate from the default values.

Run the tests

Testing the initialization is done correctly.

yarn test

Run the Local API Server in Development Mode

yarn dev

and the backend API server will listen on http://localhost:5010/api/v1

(Alternative) Development Environment To Run Inside Docker

First build the images locally and start the containers. Then iterate on the code and changes will be picked up through the mounted folders.

docker-compose up --build -d

After starting your dev server visit:

To shut down the dev server use:

docker-compose down

Development Guidelines

API Docs via Swagger

Available at http://localhost:5010/swagger/

Understand your workspace

Run nx dep-graph to see a diagram of the dependencies of your projects.

NestJS Code Generaators

We recommend using Nestjs generators to create different nestsj components in generic way.

yarn nest # will print all generators

Use the Nest resource generator to create all interfaces for CRUD operations around a new entity/resource

yarn nest generate resource [name]

Building

Run yarn build-all to build the project. The build artifacts will be stored in the dist/ directory. Use the --prod flag for a production build.

Formatting

Make sure you run auto-formatting before you commit your changes.

yarn format

Database Guidelines

For the database layer we're using Prisma. In order to get familiar with the concept please read What is Prisma? and watch some intro videos on YouTube.

Database Development Workflow

The project already contains the database shema in shema.prisma file and initialization "seed" scripts for inital data are in db/seed folder.

On an empty database

Initialize the database using these commands. It will initialize the database using the schema.prisma, the migration scripts and the db/seed scripts to insert data records for the API to work.

yarn prisma migrate deploy
yarn prisma seed

Prisma offers a nice Web Client to review and edit the database:

yarn prisma studio

Making DB Schema Changes

There are two ways to work with the database:

  • schema first - make changes in schema.prisma and update the database
  • db first - make changes directly in the database and introspect to update the schema.prisma

1. Workflow for Schema First approach (recommended)

After initializing the database, feel free to edit the schema.prisma file in the main folder. When done with changes execute to update the database:

yarn prisma migrate dev

The command will ask you to name your changes and will generate a migration script that will be saved in ./migrations folder.

Run the tests again yarn test to ensure all ok.

If you don't want to generate small migrations for every change, after finishing the work on your branch, delete the migration files manually and run again yarn prisma migrate dev to create one single feature level migration.

Read more about Team development with Prisma Migrate here.

2. Workflow for Databased First approach

After initializing the database, open prisma stidio or your favorite DB Management IDE and feel free to make db changes. When done with changes, execute:

yarn prisma db pull

This will read all changed from you db instance and will update the schema.prisma file with nessary translations.

Now that the schema file is updated, we need to update the prismajs client which is used by our app by running:

yarn prisma generate

This process is called Prisma DB Introspection.

Resetting to master

If things go bad, there is a way to reset your database to the original state. This will delete the database and will create it from the schema, executing also the seeding.

yarn prisma migrate reset

File Upload to S3

We use S3 for storing the uploaded files in buckets. The code expects the buckets to be created on prod or dev environment. We are hosting S3 ourselves using ceph https://ceph.io/en/discover/technology/.

The creation of the buckets can happen using s3cmd client https://s3tools.org/s3cmd or any other S3 client and using the S3 secrets for the respective environment.

To configure S3cmd run

s3cmd --configure

All settings are self descriptive, however pay attention to these:

  • The default region is not a Country code but "object-store-dev" for development and "object-store" for prod
  • S3 endpoint: cdn-dev.podkrepi.bg
  • When asked for DNS-style bucket use: cdn-dev.podkrepi.bg
  • When asked for encryption password just press 'Enter' for leaving it empty

Then bucket creation is like this:

s3cmd ls
s3cmd mb s3://bucket-name
s3cmd ls

Configuring Google Sign-in with Keycloak

For enabling sign-in with existing gmail account we use the token-exchange feature of Keycloak as per the great description in: https://medium.com/@souringhosh/keycloak-token-exchange-usage-with-google-sign-in-cd9127ebc96d

The logic is the following:

  1. The frontend acquires a token from Google Sign-in
  2. The frontend sends the token to the backend API requesting a login with external provider (see: auth.service.ts issueTokenFromProvider)
  3. The backend sends the token-exchange request to Keycloak passing the Google Token for Permission to Login
  4. Keycloak server grants permission and returns the access token
  5. Backend creates the new user in the database and returns the access token for use from Frontend

Production environment

Environment variables

Setting Description Default value
PORT The address on which the module binds. 5010
GLOBAL_PREFIX Registers a prefix for every HTTP route path api/v1
APP_VERSION The version of the application "unknown"
APP_ENV Application runtime environment development
NODE_ENV Node build environment development
TARGET_ENV Docker multi-stage target development
TARGET_APP Run specific application from the image. api
DATABASE_URL Database connection string. postgres://postgres:postgrespass@localhost:5432/postgres?schema=api
S3_ENDPOINT Endpoint for S3 interface. https://cdn-dev.podkrepi.bg
S3_REGION The S3 region us-east-1
S3_ACCESS_KEY The S3 access key. ******
S3_SECRET_ACCESS_KEY The S3 secret access key. ******
KEYCLOAK_URL Keycloak authentication url http://localhost:8180
KEYCLOAK_REALM Keycloak Realm name webapp
KEYCLOAK_CLIENT_ID Keycloak Client name jwt-headless
KEYCLOAK_SECRET Secret to reach Keycloak in headless mode DEV-KEYCLOAK-SECRET
KEYCLOAK_USER Master user for Keycloak Server admin
KEYCLOAK_PASSWORD Master user's password for Keycloak Server admin
STRIPE_SECRET_KEY Stripe secret key ******
STRIPE_WEBHOOK_SECRET Stripe webhook secret key ******
SENTRY_DSN Sentry Data Source Name https://[email protected]/5707518
SENTRY_ORG Sentry organization podkrepibg
SENTRY_PROJECT Sentry project rest-api
SENTRY_AUTH_TOKEN Sentry build auth token ******
SENTRY_SERVER_ROOT_DIR App directory inside the docker image /app
SENDGRID_API_KEY SendGrid API key "" - emails disabled if not set
SENDGRID_SENDER_EMAIL SendGrid sender email [email protected]
SENDGRID_INTERNAL_EMAIL Internal notification email from contact form request [email protected] (Prod), [email protected] (Dev), [email protected] (localhost)
SENDGRID_CONTACTS_URL Endpoint to receive newsletter subscriptions /v3/marketing/contacts

Deployment

CREATE SCHEMA api;
CREATE USER postgres WITH ENCRYPTED PASSWORD 'postgrespass';
GRANT ALL PRIVILEGES ON SCHEMA api TO postgres;

Migrations deployment

docker build -f Dockerfile.migrations .
docker run  --env-file .env --network host <image-id>

Manual resolution of failed db migrations

Overall procedure:

  1. Ensure a local connection to the k8s cluster
  2. Start a new migrate-database container manually in the proper namespace (podkrepibg-dev or podkrepibg).
kubectl run manual-migrate-db \
    -it --rm \
    -n podkrepibg-dev \
    --image=ghcr.io/podkrepi-bg/api/migrations:master \
    -- /bin/sh
  1. Check migration status with yarn prisma migrate status
Following migration have failed: 20220605165716_rename_bank_hash_to_payment_reference
  1. Rollback or apply migrations (suggested commands are printed from the status)
The failed migration(s) can be marked as rolled back or applied:

- If you rolled back the migration(s) manually:
yarn prisma migrate resolve --rolled-back "20220605165716_rename_bank_hash_to_payment_reference"

- If you fixed the database manually (hotfix):
yarn prisma migrate resolve --applied "20220605165716_rename_bank_hash_to_payment_reference"
  1. Run migration deployment
yarn prisma migrate deploy
  1. At this point you can re-deploy the api-headless deployment to trigger the standard flow of operation

Postman

If you'd like to use Postman to query the API - see postman doc

api's People

Contributors

aironhight avatar andreygoranov avatar angelina-7 avatar bogocvetkov avatar borislavstoychev avatar bunny303 avatar dependabot[bot] avatar dimitur2204 avatar dplamenov avatar dpmarkov avatar georgygenchev avatar igoychev avatar imilchev avatar kachar avatar kirilpopov avatar marina-yoya avatar martbul avatar nnachevvv avatar nradkova avatar pepipetrov avatar petyrdzhunov avatar quantum-grit avatar sashko9807 avatar slavcho avatar stann1 avatar stilian-nikolaev avatar todorbelchev avatar tongo-angelov avatar valkirilov avatar yakimov1337 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

api's Issues

Add API versioning

  • Display version in root endpoint
  • Display the version in swagger endpoint /docs
  • Use only tagged docker images when deploying to prod
  • Use master docker images when deploying to dev

Integrate authorization layer

Close the donation campaign once the targeted amount is reached

We want to close the campaign for further donations from the UI by providing a proper state.

Once the frontend sees that state they'll hide the buttons for donation. if the user has opened the page for donation before it has reached the amount, we better let him donate to it even though it will go over the limit,

Example:

  • current 980
  • target 1000
  • donation of 20 should lead to 1000 and close further donations
  • donation of 100 should lead to 1080 and close further donations

What we don't want:

  • To cap the campaign at exact target amount
  • To limit stripe transactions reach their destination campaign
  • To show error when users are trying to create a new checkout session

[Campaign] Create endpoint for loading public campaign donation history

The API should enable loading the details of the donation made for specific campaign.

Note, that anonymous donations should be loaded with Name=anonymous.

The dataset should be selected from PrismaDb Client using Campaign.Vaults.Donations and for now only these fields are interesting donorName, donationAmount, donationTime

list beneficients via api

Exposed at /beneficiary/list

[
  {
    "id": "0d905041-6020-4a2a-91b3-7d22f3686a0f",
    "type": "individual",
    "personId": "761cd680-8a1f-4030-a753-ea7bf7b675af",
    "coordinatorId": "6b6b2d6e-0b0e-4c9f-821b-ab469481507c",
    "countryCode": "BG",
    "cityId": "1e52bcc0-c20d-4540-b9b0-f37c3172e232",
    "description": null,
    "publicData": null,
    "privateData": null,
    "createdAt": "2021-09-20T13:24:13.825Z",
    "updatedAt": "2021-09-20T13:24:13.825Z",
    "coordinatorRelation": "none"
  }
]

Use node process manager to run the api

At the moment we use node to run the main process, but this is not convenient as on every crash of the API another pod needs to be recreated which takes time.

We need to switch to a better process strategy

crud for Country entity (api)

Implement all crud operations for Country entity

  • create country
  • get all countries
  • get country by Id
  • update country
  • remove country by Id

Make Keycloack login with grant manager instead of admin cli

At the moment during login we authenticate the admin client as the user which is logically incorrect.

We need to pass the keycloak instance and use KeycloakConnect.GrantManager to create the jwt token for the user after they provide their email and password

Use consistent api naming convention

At the moment the endpoint /beneficiary/create-beneficiary shows results in both snake case and camel case

Fields: created_at and updated_at should be camel cased as well

{
  "id": "bd67d80f-38d0-41ac-896a-972134d83563",
  "type": "individual",
  "personId": "1ae4d99b-a8f1-458c-a4f9-8d8eebbc2dc2",
  "countryCode": "BG",
  "cityId": "c7cf8351-562d-418a-b832-fade92a412ab",
  "details": {
    "test": "best"
  },
  "coordinatorId": "e9b4a999-1dab-41d6-9bda-5c1284e3a160",
  "coordinatorRelation": "brother",
  "created_at": "2021-09-18T07:03:00.418Z",
  "updated_at": "2021-09-18T07:03:00.418Z"
}

Create campaign module

  • create new campaign at /campaign/create-campaign
  • list campaigns at /campaign/list
  • list campaign types at /campaign-type/list

Nestjs warning about annotated imports

cd api
yarn dev

WARN [DependenciesScanner] In the next major version, Nest will not allow classes annotated with @Injectable(), @catch(), and @controller() decorators to appear in the "imports" array of a module.
Please remove "JsonBodyMiddleware" (including forwarded occurrences, if any) from all of the "imports" arrays.

WARN [DependenciesScanner] In the next major version, Nest will not allow classes annotated with @Injectable(), @catch(), and @controller() decorators to appear in the "imports" array of a module.
Please remove "RawBodyMiddleware" (including forwarded occurrences, if any) from all of the "imports" arrays.

Scope [AppModule]

Add login and register functionality

In order to deliver a robust authentication we should register and login the users via the API layer instead of redirect flow via Keycloak. Redirect flow is okay to stay only for external oauth providers like google, facebook, etc

At the moment only Keycloak registrations are allowed which limit us in the way we manage user's profiles

The goal of this issue is to deliver the following functionalities:

  • login endpoint that accepts email and password
  • generation of authentication jwt from keycloak based on the input
  • register endpoint that accepts email, password, firstName and lastName
  • creation of account in keycloak based on the input
  • create person for each new registration
  • match the person id to keycloak id (jwt subject)

Keycloak config

Add healthcheck endpoint

Add an endpoint that can be queried to check the health of the module. Preferably that endpoint will only return HTTP OK if a connection with the database can be established.

Create beneficent module

  • create module
  • create beneficent via api
  • create coordinator via api
  • create country seed
  • create city seed
  • add person relation enum
  • #14

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.