Before you begin, ensure you have the following installed on your system:
- Node.js: Version 22.13.1 is recommended. Using nvm is advised:
nvm install 22.13.1 nvm use 22.13.1
- pnpm: Install globally using npm:
npm install -g pnpm
- PostgreSQL Client (
psql
): Required for importing the database dump. Install the command-line tools from the official PostgreSQL website. - MySQL Client (
mysql
): Required for importing the legacy authorization dump before migration. Install the command-line tools from the official MySQL website. - Docker: The latest version of Docker Desktop or Docker Engine is needed to run the databases and Redis. Download from the official Docker website.
This service uses two separate PostgreSQL databases running in Docker:
common_oltp_db
: Contains existing tables and data (from an imported dump).authorization_db
: New database for tables migrated from MySQL (managed by Prisma Migrate).
Additionally, a temporary MySQL database is used during the legacy data migration process.
Follow these steps to set up and run the application locally:
-
Install Dependencies: Clone the repository and install the necessary Node.js packages using pnpm.
pnpm install
(This command also runs
pnpm run prisma:generate
automatically via thepostinstall
script to generate Prisma clients for both databases.) -
Configure Environment: Copy the example environment file and update the necessary variables.
cp .env.sample .env
- Crucially, update
AUTH_SECRET
to a strong, unique secret key for local HS256 JWT generation. Do not use the default placeholder. - Crucially, update
AUTH0_CLIENT_SECRET
as provided in the forum. - Verify database connection URLs (
COMMON_OLTP_DB_URL
,AUTHORIZATION_DB_URL
), database names (COMMON_OLTP_DB_NAME
,AUTHORIZATION_DB_NAME
), ports (DB_PORT
,MYSQL_PORT
), and credentials (DB_USERNAME
,DB_PASSWORD
). The defaults in.env.sample
usually work with the provideddocker-compose.yml
. - Ensure
JWT_VALIDATION_MODE
is set toHS256
for local development (this is the default in.env.sample
).
- Crucially, update
-
Start Services: Launch the PostgreSQL databases, MySQL database (for migration), and Redis using Docker Compose.
docker compose up -d
- Wait a few moments for the databases to initialize completely.
-
Import Common OLTP Data: Import the
common_oltp
database dump into thecommon_oltp_db
PostgreSQL database.# Replace ~/Downloads/common_oltp with the actual path to your dump file. (Download it from forum, and extract from zip) - Use password from DB_PASSWORD of .env file # Ensure DB_HOST, DB_PORT, DB_USERNAME, and COMMON_OLTP_DB_NAME match your .env values. psql -h ${DB_HOST:-127.0.0.1} -p ${DB_PORT:-5432} -U ${DB_USERNAME:-topcoderuser} \ -d ${COMMON_OLTP_DB_NAME:-common_oltp_db} \ -f ~/Downloads/common_oltp -v ON_ERROR_STOP=0
-
Initialize Authorization Database Schema: Apply the Prisma migrations to create the necessary tables in the
authorization_db
PostgreSQL database.pnpm prisma migrate dev --name init --schema prisma/authorization/schema.prisma
-
Migrate Legacy Authorization Data: This step involves importing data from a legacy MySQL dump into the temporary MySQL container and then migrating it to the new
authorization_db
PostgreSQL database.- Import MySQL Dump:
# Replace ~/Downloads/Authorization with the actual path to your MySQL dump file (Download it from forum, and extract from zip) # Ensure MYSQL_HOST, MYSQL_PORT, MYSQL_USER, MYSQL_PASSWORD, and MYSQL_DATABASE match your .env values. Use the password from .env when asked. mysql -h ${MYSQL_HOST:-127.0.0.1} -P ${MYSQL_PORT:-3306} -u ${MYSQL_USER:-root} -p${MYSQL_PASSWORD:-mysql-user-root-password} ${MYSQL_DATABASE:-authorization_db} < ~/Downloads/Authorization
- Run Migration Script:
pnpm run db:migrate-legacy
- Import MySQL Dump:
-
Run Unit Tests: You can run the unit tests to verify the setup.
pnpm run test [email protected] test > jest PASS src/api/role/role.service.spec.ts (5.636 s) PASS src/api/user/user.service.spec.ts (5.657 s) PASS src/api/role/role.controller.spec.ts (5.674 s) PASS src/api/user/user.controller.spec.ts (6.036 s) Test Suites: 4 passed, 4 total Tests: 83 passed, 83 total Snapshots: 0 total Time: 6.715 s Ran all test suites.
-
Generate an Admin Token: For interacting with the API locally (e.g., via Postman), generate a test JWT using the provided script. This requires
JWT_VALIDATION_MODE=HS256
and a definedAUTH_SECRET
in your.env
file.# Generate a default admin token (expires in 8 hours) node scripts/generate-local-token.js
Copy the generated token (the long string starting with
eyJ...
). See the "Generating Local HS256 Tokens" section below for more options. -
Update Postman Environment file You'll need to update the Authorization Bearer token in the
doc/postman_environment.json
with the one generated in the previous step. -
Start the Application: Run the NestJS application in development mode (with hot-reloading).
pnpm run start:dev
The API should now be available, at
http://localhost:3000
. -
Run Postman/Newman Tests: After starting the application, you can run the individual Postman collection tests using Newman. Ensure your Postman environment (
doc/postman_environment.json
) is configured, especially thebaseUrl
andaccessToken
.- Roles API Tests:
pnpm run test:postman:roles
- Users API Tests:
- Import
doc/postman_environment
andusers.postman_collection.json
to your postman app. These tests cannot be fully automated because it requires getting tokens from emails. - Follow the video
users-endpoint.mp4
to test all endpoints provided with a sample email.
Use below command to generate a user token
node scripts/generate-local-token.js "100000157" "Topcoder User" "user100000147handle" "[email protected]" "read:dice,write:dice" "1h"
- Roles API Tests:
Prisma is configured to manage both databases separately.
-
For the
authorization_db
Database:- This database schema is managed by Prisma Migrate.
- To create the database and apply migrations during development:
pnpm run prisma:migrate:authorization
- To apply migrations in production-like environments:
pnpm run prisma:deploy:authorization
- Generate the client if needed:
pnpm run prisma:generate:authorization
-
For the
common_oltp_db
Database:- This database uses an imported dump. If the dump changes, or for initial setup verification, you can update the Prisma schema to match the database:
pnpm run prisma:pull:common_oltp
- After pulling, regenerate the client if needed (though
pnpm install
should handle it):pnpm run prisma:generate:common_oltp
- This database uses an imported dump. If the dump changes, or for initial setup verification, you can update the Prisma schema to match the database:
-
Prisma Studio (for browsing data):
- Open Studio for
common_oltp_db
(runs on port 5555):pnpm run prisma:studio:common_oltp
- Open Studio for
authorization_db
(runs on port 5556):pnpm run prisma:studio:authorization
- Open both studios concurrently:
pnpm run prisma:studio
- Open Studio for
The pnpm run db:migrate-legacy
script handles the migration from a temporary MySQL database (populated from a dump) to the authorization_db
PostgreSQL database.
- Ensure MySQL Container is Running: The
docker-compose up -d
command should start a MySQL service (checkdocker-compose.yml
). - Import the MySQL Dump: Use the
mysql
command-line tool to import your legacyAuthorization
dump into the running MySQL container. See Step 6 in the "Local Development Setup" for the command. Ensure connection details match your.env
configuration (MYSQL_HOST
,MYSQL_PORT
, etc.). - Run the Migration Script: Execute the script to transfer and transform the data.
pnpm run db:migrate-legacy
The following table summarizes the environment variables used by the application. Copy .env.sample
to .env
and customize these values as needed.
Variable | Description | Default Value (.env.sample ) |
---|---|---|
NODE_ENV |
Application environment (e.g., development , production ) |
development |
PORT |
Port the application listens on | 3000 |
Database (PostgreSQL - Common OLTP) | ||
DB_HOST |
Hostname for the main PostgreSQL database | 127.0.0.1 |
DB_PORT |
Port for the main PostgreSQL database | 5432 |
DB_USERNAME |
Username for the main PostgreSQL database | topcoderuser |
DB_PASSWORD |
Password for the main PostgreSQL database | randompassword |
COMMON_OLTP_DB_NAME |
Name of the main PostgreSQL database | common_oltp_db |
Database (PostgreSQL - Authorization) | ||
AUTHORIZATION_DB_NAME |
Name of the authorization PostgreSQL database | authorization_db |
Database (MySQL - Legacy Migration) | ||
MYSQL_HOST |
Hostname for the temporary MySQL database (for migration) | 127.0.0.1 |
MYSQL_PORT |
Port for the temporary MySQL database | 3307 |
MYSQL_USER |
Username for the temporary MySQL database | root |
MYSQL_PASSWORD |
Password for the temporary MySQL database | mysql-user-root-password |
MYSQL_DATABASE |
Name of the temporary MySQL database | authorization_db |
Redis Cache | ||
REDIS_HOST |
Hostname for the Redis cache instance | 127.0.0.1 |
REDIS_PORT |
Port for the Redis cache instance | 6380 |
JWT Validation | ||
JWT_VALIDATION_MODE |
Validation mode: HS256 (local) or RS256 (prod/staging) |
HS256 |
AUTH_SECRET |
Secret key for HS256 token generation/validation (local only). CHANGE THIS! | <<<REPLACE WITH A REAL SECRET KEY>>> |
JWT_ISSUER_URL |
Expected issuer URL in JWTs | https://api.topcoder-dev.com |
JWT_AUDIENCE |
Expected audience in JWTs | www.example.com |
JWT_JWKS_URI |
JWKS endpoint URI for RS256 validation (prod/staging only) | (commented out) |
DICE Authentication | ||
DICEAUTH_DICE_API_URL |
Base URL for the DICE API. | https://console-api-uat.diceid.com/v1 (example) |
DICEAUTH_DICE_API_KEY |
API key for authenticating with the DICE API (used in x-api-key header). |
wGu5zRfmgJ8zP... (example) |
DICEAUTH_ORG_ID |
Organization ID for DICE API calls (used in org_id header). |
4f541723-f581-44de-b61c-5f83e8b8ef1e (example) |
DICEAUTH_USER_ID |
User ID for invoking DICE APIs (used in invoked_by header). |
a5e7e72a-fa5e-4acf-9eca-741d1443279b (example) |
DICEAUTH_TC_API_KEY |
API key used by this application to validate incoming webhooks from DICE. | iQEErpTqL7ZiX... (example) |
DICEAUTH_SCHEMA_NAME |
Name of the credential schema used in DICE. | Topcoder (example) |
DICEAUTH_SCHEMA_VERSION |
Version of the credential schema used in DICE. | 1.4 (example) |
DICEAUTH_OTP_DURATION |
OTP validity duration in minutes (e.g., for 2FA flows). Defaults to 10 if DEV_DICEAUTH_OTP_DURATION is used by code and not set. |
10 (example, in minutes) |
Slack Integration | ||
SLACK_BOT_KEY |
Bot token for Slack API authentication. | xoxb-3858018789-... (example) |
SLACK_CHANNEL_ID |
Default Slack channel ID for sending notifications. | C04ENKCU4TZ (example) |
SendGrid Integration | ||
SENDGRID_RESEND_ACTIVATION_EMAIL_TEMPLATE_ID |
SendGrid template ID for resend activation email. | d-73c29be82bfa4d68beea2208b6a3c4b2 (example) |
SENDGRID_WELCOME_EMAIL_TEMPLATE_ID |
SendGrid template ID for welcome email. | d-26c8962fb48c42a3997053ebe5954516 (example) |
Other | ||
ADMIN_ROLE_NAME |
Name of the role considered admin | administrator |
LOG_LEVEL |
Logging level (e.g., debug , info , warn , error ) |
info |
JWT_SECRET |
Secret key for signing/verifying internal JWTs (e.g., 2FA, one-time tokens). | just-a-random-string (example) |
LEGACY_BLOWFISH_KEY |
Base64 encoded Blowfish key for legacy password encryption/decryption. | dGhpc2lzRGVmYXVmZlZhbHVl (example) |
The application supports two JWT validation modes, configured via JWT_VALIDATION_MODE
:
1. Local Development (HS256 Mode - Recommended)
Use this mode for local testing, allowing you to generate tokens easily without needing an external IdP.
- Set
JWT_VALIDATION_MODE=HS256
- Set
AUTH_SECRET
to a strong, unique secret key. Do not use the default placeholder. - Optionally, set
JWT_ISSUER_URL
andJWT_AUDIENCE
to match the values you intend to put in your generated tokens (defaults are provided). - Comment out or remove
JWT_JWKS_URI
.
2. Production/Staging (RS256 Mode - Default)
Use this mode when deploying, validating tokens against a real identity provider (like Auth0).
- Set
JWT_VALIDATION_MODE=RS256
or omit the variable. - Set
JWT_ISSUER_URL
to your IdP's issuer URL. - Set
JWT_AUDIENCE
to your API's audience identifier registered with the IdP. - Set
JWT_JWKS_URI
to the JWKS endpoint of your IdP. - Comment out or remove
AUTH_SECRET
.
# development
$ pnpm run start
# watch mode
$ pnpm run start:dev
# production mode
$ pnpm run start:prod
# unit tests
$ pnpm run test
# e2e tests
$ pnpm run test:e2e
# test coverage
$ pnpm run test:cov
# Install dependencies
pnpm install
# Run database migrations (if applicable)
# Example: pnpm prisma migrate dev --schema=./prisma/authorization.prisma
# Example: pnpm prisma migrate dev --schema=./prisma/common_oltp.prisma
# Start the application in development mode (with hot-reloading)
pnpm run start:dev
When running in HS256
mode locally, you can generate valid JWTs using the provided script:
-
Ensure
.env
is configured:JWT_VALIDATION_MODE=HS256
AUTH_SECRET
is set to your chosen secret key.JWT_ISSUER_URL
,JWT_AUDIENCE
are set (optional, defaults used if not).
-
Run the script:
node scripts/generate-local-token.js [userId] [roles] [handle] [email] [expiresIn]
- Arguments are optional and default to values similar to the
ADMIN_TOKEN
. roles
: Comma-separated list (no spaces around commas), e.g.,administrator,Topcoder\ User
expiresIn
: Time string like1h
,8h
,1d
.
- Arguments are optional and default to values similar to the
-
Examples:
# Generate default admin token (expires in 8h) node scripts/generate-local-token.js # Generate token for a regular user (ID 12345, handle 'testuser') node scripts/generate-local-token.js 12345 "Topcoder User" testuser [email protected] # Generate admin token expiring in 1 hour node scripts/generate-local-token.js 8547899 administrator "TonyJ" "[email protected]" 1h
-
Use the Output: Copy the generated token and use it in the
Authorization: Bearer <token>
header of your API requests (e.g., in Postman).
# unit tests
pnpm run test
# Run Postman collection via Newman (requires app running)
pnpm run test:postman
# e2e tests (currently placeholder/not fully configured)
# pnpm run test:e2e
# test coverage
pnpm run test:cov