NestJS authentication starter for a multivendor futsal platform.
- Separate tables for regular users and ground-owner/admin accounts
- JWT login and registration for both account types
- PostgreSQL database wiring through TypeORM
- Validation and password hashing
- Copy
.env.exampleto.envand set your ownJWT_SECRET. - Install dependencies.
- Run the app in development mode.
npm install
npm run start:devThe app runs pending TypeORM migrations on startup. When you change an entity, generate a new migration and commit it with the code change.
npm run migration:generate -- src/migrations/YourMigrationName
npm run migration:runThe generate command should point to a new file name for each schema change.
Run the app and database together with Docker Compose:
docker compose up --buildPostgreSQL will be available on host port 0001, mapped to container port 5432.
The API will be available on host port 1111.
The app loads secrets from .env, waits for Postgres to become healthy, then runs pending migrations before starting.
POST /auth/users/request-otpPOST /auth/users/register(legacy alias ofPOST /auth/users/request-otp)POST /auth/users/verify-otpPOST /auth/users/loginPOST /auth/admins/request-otpPOST /auth/admins/register(legacy alias ofPOST /auth/admins/request-otp)POST /auth/admins/verify-otpPOST /auth/admins/loginGET /auth/meGET /fields(public list of active fields)GET /fields/mine(admin only)POST /fields(admin only)POST /fields/bulk(admin only, create multiple fields at once)
- One admin can own multiple fields.
- Field names are unique per owner (same name can be used by different owners).
- Fields are separated by owner to support multi-tenant usage.
- Call
POST /auth/users/request-otpwithusername,password, and eitheremailormobileNumber. - OTP is stored hashed in the database and delivered through your email/SMS integration later.
- Call
POST /auth/users/verify-otpwith the same identifier and the OTP. - The account is created only after OTP verification.
POST /auth/admins/request-otprequiresusername,email, andpassword(also accepts legacyownerName).groundNamewill be captured in a later onboarding phase.POST /auth/users/loginacceptsemail,mobileNumber, orusernamewithpassword.- OTP values are not returned in API responses or logged in plain text.
- OTP values are stored in the OTP request table as both
raw_otpandotp_hash.
- Call
POST /auth/admins/request-otpwithusername,email, andpassword. - OTP is stored hashed in the database and delivered through your email integration later.
- Call
POST /auth/admins/verify-otpwith the same email and OTP. - The admin account is created only after OTP verification.
synchronizeis disabled (DB_SYNCHRONIZE=false) for local and Docker environments.- Use migrations for all schema changes.
RESET_PROD_CONFIRM=RESET_PROD npm run db:reset:prod