User Service (user-app)
Relevant source files
The following files were used as context for generating this wiki page:The User Service (user-app) is a core microservice within the e-commerce platform, built using the NestJS framework. Its primary responsibilities include managing user data, handling user authentication and authorization, and managing user addresses. It communicates with other services, such as the API Gateway, via the NATS messaging system.
This service is a critical component in the system's startup sequence, as it is responsible for generating and distributing the public key used for JWT verification across the platform. It uses a dedicated PostgreSQL database (user_db) and Prisma as its ORM for all data persistence.
Sources: README.md, deploys/README.md, SETUP.md
Architecture
The user-app operates as a standalone NestJS application within a larger microservices architecture. It listens for incoming requests on specific NATS subjects and interacts with its own PostgreSQL database.
This diagram illustrates the position of the user-app within the overall system architecture.
Sources: deploys/README.md, SETUP.md
Database Schema
The service's data models are defined in schema.prisma. The core entities are User and Address.
This Entity-Relationship diagram shows the database models and their relationships managed by the user-app.
User Model
The User model stores essential information about users, including credentials and roles.
| Field | Type | Description | Constraints |
|---|---|---|---|
id | String | Unique identifier for the user. | @id @default(cuid()) |
email | String | User's email address, used for login. | @unique |
passwordHash | String | Hashed user password. | |
fullName | String | User's full name. | |
phone | String | User's phone number. | Optional (?) |
role | UserRole | User's role (ADMIN or CUSTOMER). | @default(CUSTOMER) |
isActive | Boolean | Flag to indicate if the account is active. | @default(true) |
addresses | Address[] | A list of the user's saved addresses. | Relation |
Address Model
The Address model stores shipping addresses associated with a user.
| Field | Type | Description | Constraints |
|---|---|---|---|
id | String | Unique identifier for the address. | @id @default(cuid()) |
userId | String | Foreign key linking to the User model. | |
fullName | String | Recipient's full name for this address. | |
phone | String | Recipient's phone number. | |
street | String | Street and house number. | |
ward | String | Ward name. | |
district | String | District name. | |
province | String | Province or City name. | |
isDefault | Boolean | Indicates if this is the user's default address. | @default(false) |
Sources: apps/user-app/prisma/schema.prisma
Core Services
Authentication Service (AuthService)
The AuthService handles all authentication-related logic, including user registration, login, and token management.
Key Responsibilities:
- User Validation: Compares provided passwords with the stored hash using
bcryptjs. - Token Generation: Signs JWTs (access and refresh tokens) using an RSA private key.
- Registration: Creates new users via the
UsersService. - Public Key Distribution: On startup, it publishes the RSA public key to a NATS subject (
auth.public-key) for other services like the Gateway to consume for token verification.
Sources: apps/user-app/src/auth/auth.service.ts, deploys/README.md
Login Flow
The following sequence diagram illustrates the user login process, from the initial request at the API Gateway to the token generation in the user-app.
Users Service (UsersService)
The UsersService is responsible for all CRUD operations related to user entities.
Key Methods:
create(dto): Creates a new user. It first checks if the email already exists, then hashes the password usingbcrypt.hashbefore saving the new user to the database.findById(id): Retrieves a user by their unique ID. Throws anRpcExceptionif not found.findByEmail(email): Retrieves a user by their email. Throws anRpcExceptionif not found.update(id, dto): Updates a user's information.deactivate(id): Sets theisActiveflag for a user tofalse.list(query): Returns a paginated list of users, with support for searching by email or full name and filtering by role.
The service consistently uses select clauses in its Prisma queries to ensure that sensitive data like passwordHash is not returned unless explicitly needed.
Sources: apps/user-app/src/users/users.service.ts, apps/user-app/src/users/users.service.spec.ts
Address Service (AddressService)
The AddressService manages the shipping addresses associated with users.
Key Methods:
create(userId, dto): Creates a new address for a specific user.findAllForUser(userId): Retrieves all addresses belonging to a user.update(userId, addressId, dto): Updates an existing address, ensuring the address belongs to the specified user.remove(userId, addressId): Deletes an address, verifying ownership first.setDefault(userId, addressId): Sets a specific address as the user's default. This involves a transaction to set the new default and unset any previous default.
All methods perform ownership checks to prevent users from accessing or modifying addresses that do not belong to them.
Sources: apps/user-app/src/address/address.service.ts
NATS Message Patterns
The service exposes its functionality through NATS message patterns, which are handled by its controllers. The API Gateway communicates with user-app by sending messages to these subjects.
| NATS Subject (Event) | Controller Method | Description |
|---|---|---|
EVENTS.AUTH.REGISTER | AuthController.register() | Registers a new user. |
EVENTS.AUTH.LOGIN | AuthController.login() | Logs a user in and returns tokens. |
EVENTS.AUTH.VERIFY_TOKEN | AuthController.verifyToken() | Verifies a JWT. |
EVENTS.USER.CREATE | UsersController.create() | Creates a new user (admin action). |
EVENTS.USER.FIND_BY_ID | UsersController.findById() | Finds a user by their ID. |
EVENTS.USER.FIND_BY_EMAIL | UsersController.findByEmail() | Finds a user by their email. |
EVENTS.USER.UPDATE | UsersController.update() | Updates user details. |
EVENTS.USER.DEACTIVATE | UsersController.deactivate() | Deactivates a user account. |
EVENTS.USER.LIST | UsersController.list() | Lists all users with pagination and filtering. |
EVENTS.ADDRESS.CREATE | AddressController.create() | Creates a new address for the current user. |
EVENTS.ADDRESS.FIND_ALL | AddressController.findAll() | Finds all addresses for the current user. |
EVENTS.ADDRESS.UPDATE | AddressController.update() | Updates a specific address. |
EVENTS.ADDRESS.DELETE | AddressController.remove() | Deletes a specific address. |
EVENTS.ADDRESS.SET_DEFAULT | AddressController.setDefault() | Sets an address as the default. |
Sources: apps/gateway/README.md, apps/user-app/src/users/users.controller.spec.ts
Deployment and Configuration
The user-app is designed to be deployed as a Docker container. It has a critical role in the system's startup order.
Startup Order
- PostgreSQL Server
- NATS Server
- User-app (must start to publish the JWT public key)
- API Gateway (waits for the public key from
user-app) - Other microservices
This order is crucial because the API Gateway depends on the public key published by the user-app to verify JWTs for incoming requests.
Environment Variables
The service requires the following environment variable for its database connection:
DATABASE_URL_USER: The connection string for theuser_dbPostgreSQL database.- Format:
postgresql://user:password@host:port/database
- Format:
Sources: deploys/README.md, libs/shared/config/env.validation.spec.ts