👤 User Service
The User Service provides a complete REST API for managing user entities with CRUD operations. It's built using the Nodeblocks functional composition approach and integrates seamlessly with MongoDB.
🚀 Quickstart
import express from 'express';
import { middlewares, services, drivers } from '@nodeblocks/backend-sdk';
const { nodeBlocksErrorMiddleware } = middlewares;
const { userService } = services;
const { withMongo } = drivers;
const connectToDatabase = withMongo('mongodb://localhost:27017', 'dev', 'user', 'password');
express()
.use(
userService(
{
...(await connectToDatabase('users')),
...(await connectToDatabase('identities')),
...(await connectToDatabase('organizations')),
...(await connectToDatabase('products')),
},
{
authSecrets: {
authEncSecret: 'your-encryption-secret',
authSignSecret: 'your-signing-secret',
},
identity: {
typeIds: {
admin: '100',
guest: '000',
regular: '001',
},
},
}
)
)
.use(nodeBlocksErrorMiddleware())
.listen(8089, () => console.log('Server running'));
📋 Endpoint Summary
| Method | Path | Description | Authorization |
|---|---|---|---|
POST | /users | Create a new user | Bearer token required |
GET | /users/:profileId | Retrieve a user by ID | Bearer token required (admin or profile owner) |
GET | /users | List/filter users | Bearer token required (admin only) |
GET | /profiles/identities/:identityId | Retrieve user profiles by identity ID | Bearer token required (self-access only) |
PATCH | /users/:profileId | Update a user | Bearer token required (admin or profile owner) |
DELETE | /users/:profileId | Delete a user | Bearer token required (admin or profile owner) |
File Upload Operations
| Method | Path | Description | Authorization |
|---|---|---|---|
GET | /user-profiles/:profileId/avatar-upload-url | Get signed URL to upload user avatar | Bearer token required (admin or profile owner) |
Profile Follow Operations
| Method | Path | Description | Authorization |
|---|---|---|---|
PUT | /profiles/:profileId/profile-follows/:followProfileId | Create a profile follow relationship | Bearer token required (admin or profile owner) |
DELETE | /profiles/:profileId/profile-follows/:followProfileId | Delete a profile follow relationship | Bearer token required (admin or profile owner) |
GET | /profiles/:profileId/followers | Get profile followers with pagination | Bearer token required (admin or profile owner) |
Organization Follow Operations
| Method | Path | Description | Authorization |
|---|---|---|---|
PUT | /profiles/:profileId/organization-follows/:followOrganizationId | Create an organization follow relationship | Bearer token required (admin or profile owner) |
DELETE | /profiles/:profileId/organization-follows/:followOrganizationId | Delete an organization follow relationship | Bearer token required (admin or profile owner) |
Product Like Operations
| Method | Path | Description | Authorization |
|---|---|---|---|
PUT | /profiles/:profileId/product-likes/:likeProductId | Create a product like relationship | Bearer token required (admin or profile owner) |
DELETE | /profiles/:profileId/product-likes/:likeProductId | Delete a product like relationship | Bearer token required (admin or profile owner) |
🗄️ Entity Schema
The user entity combines base fields (auto-generated) with user-specific data:
{
"id": "string",
"createdAt": "string (datetime)",
"updatedAt": "string (datetime)",
"identityId": "string",
"name": "string",
"avatar": {
"url": "string",
"objectId": "string"
} | null,
"profileFollows": [
{
"followProfileId": "string"
}
],
"organizationFollows": [
{
"followOrganizationId": "string"
}
],
"productLikes": [
{
"likeProductId": "string"
}
]
}
Field Details
| Field | Type | Auto-Generated | Required | Description |
|---|---|---|---|---|
id | string | ✅ | ✅ | Unique identifier (UUID) |
createdAt | datetime | ✅ | ✅ | Creation timestamp |
updatedAt | datetime | ✅ | ✅ | Last modification timestamp |
identityId | string | ❌ | ✅ | Linked identity identifier |
name | string | ❌ | ✅ | User's display name |
avatar | object or null | ❌ | ❌ | User avatar metadata or null |
profileFollows | array | ✅ | ✅ | Array of profile follow relationships (initialized as empty array) |
organizationFollows | array | ✅ | ✅ | Array of organization follow relationships (initialized as empty array) |
productLikes | array | ✅ | ✅ | Array of product like relationships (initialized as empty array) |
📝 Note: Auto-generated fields are set by the service and should not be included in create/update requests.
🖼️ Avatar: The
avatarfield can benullor an object with storage metadata.
🔐 Authentication Headers
For all endpoints, include the following headers:
Authorization: Bearer <access_token>
x-nb-fingerprint: <device_fingerprint>
⚠️ Important: The
x-nb-fingerprintheader is required for all authenticated requests if fingerprint was specified during authorization. Without it, requests will return 401 Unauthorized.
🔧 API Endpoints
1. Create User
Creates a new user with the provided information.
Request:
- Method:
POST - Path:
/users - Headers:
Content-Type: application/jsonAuthorization: Bearer <token>x-nb-fingerprint: <device-fingerprint>
- Authorization: Bearer token required
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
identityId | string | ✅ | Linked identity identifier |
name | string | ✅ | User's display name |
Response Body:
| Field | Type | Description |
|---|---|---|
id | string | Unique user identifier |
identityId | string | Linked identity identifier |
name | string | User's display name |
avatar | object or null | User avatar metadata or null |
createdAt | string | Creation timestamp |
updatedAt | string | Last update timestamp |
Validation:
- Schema Validation: Enforced automatically (identityId and name required; no additional properties)
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or self for the target identity
Example Request:
curl -X POST {{host}}/users \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{
"identityId": "811ff0a3-a26f-447b-b68a-dd83ea4000b9",
"name": "John Doe"
}'
Success Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"identityId": "811ff0a3-a26f-447b-b68a-dd83ea4000b9",
"name": "John Doe",
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T09:41:22.552Z"
}
Error Responses:
When request body is missing required fields:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'identityId'",
"request body must have required property 'name'",
"request body must NOT have additional properties"
]
}
}
When no authorization token is provided:
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"error": {
"message": "token could not be verified"
}
}
When database insert operation fails to return an inserted ID:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Failed to create user"
}
}
When an unexpected error occurs (database connection issues, etc.):
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to create user"
}
}
2. Get User by ID
Retrieves a specific user by their unique ID.
Request:
- Method:
GET - Path:
/users/:profileId - Headers:
Authorization: Bearer <token>x-nb-fingerprint: <device-fingerprint>
- Authorization: Bearer token required (admin or profile owner)
URL Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
profileId | string | ✅ | Unique user profile identifier |
Response Body:
| Field | Type | Description |
|---|---|---|
id | string | Unique user identifier |
identityId | string | Linked identity identifier |
name | string | User's display name |
avatar | object or null | User avatar metadata or null |
createdAt | string | Creation timestamp |
updatedAt | string | Last update timestamp |
Validation:
- Schema Validation: Path parameter validation (profileId required)
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or owner of the target profile
Example Request:
curl {{host}}/users/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2 \
-H "Authorization: Bearer your-access-token-here"
Success Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"identityId": "811ff0a3-a26f-447b-b68a-dd83ea4000b9",
"name": "John Doe",
"avatar": null,
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T09:41:22.552Z"
}
Error Responses:
When no authorization token is provided:
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"error": {
"message": "token could not be verified"
}
}
When the user is not authorized to access this resource:
HTTP/1.1 403 Forbidden
Content-Type: application/json
{
"error": {
"message": "Identity is not authorized to access this resource"
}
}
When no user exists with the provided ID:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "User profile not found"
}
}
When an unexpected error occurs (database connection issues, etc.):
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to get user"
}
}
3. List Users
Retrieves a list of users with optional filtering and pagination.
Request:
- Method:
GET - Path:
/users - Headers:
Authorization: Bearer <token>x-nb-fingerprint: <device-fingerprint>
- Authorization: Bearer token required (admin only)
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
identityId | string | ❌ | Filter users by identity identifier |
name | string | ❌ | Filter users by display name |
page | number | ❌ | Page number (1-1000) |
limit | number | ❌ | Items per page (1-50) |
Response Body:
| Field | Type | Description |
|---|---|---|
data | array | Array of user objects |
metadata | object | Response metadata |
metadata.pagination | object | Pagination information |
Each user object in the data array contains:
| Field | Type | Description |
|---|---|---|
id | string | Unique user identifier |
identityId | string | Linked identity identifier |
name | string | User's display name |
avatar | object or null | User avatar metadata or null |
profileFollows | array | Array of profile follow relationships |
organizationFollows | array | Array of organization follow relationships |
productLikes | array | Array of product like relationships |
createdAt | string | Creation timestamp |
updatedAt | string | Last update timestamp |
Validation:
- Schema Validation: Query parameter validation for name (string), page and limit (integers with min/max constraints)
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role
Example Requests:
List all users:
curl {{host}}/users \
-H "Authorization: Bearer <access-token>"
Filter by identity ID:
curl "{{host}}/users?identityId=811ff0a3-a26f-447b-b68a-dd83ea4000b9" \
-H "Authorization: Bearer <access-token>"
Filter by name:
curl "{{host}}/users?name=John" \
-H "Authorization: Bearer <access-token>"
Combine filters:
curl "{{host}}/users?name=John&page=1&limit=20" \
-H "Authorization: Bearer <access-token>"
Success Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"data": [
{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"identityId": "811ff0a3-a26f-447b-b68a-dd83ea4000b9",
"name": "John Doe",
"avatar": null,
"profileFollows": [],
"organizationFollows": [],
"productLikes": [],
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T09:41:22.552Z"
},
{
"id": "8fec096b-1bc7-5bfe-c827-3600e8fe2790",
"identityId": "922ff1b4-b37g-558c-c79b-ee94fb5001c0",
"name": "Jane Smith",
"avatar": {
"url": "https://storage.example.com/avatars/avatar123.png",
"type": "image/png"
},
"profileFollows": [],
"organizationFollows": [],
"productLikes": [],
"createdAt": "2024-05-29T10:15:33.441Z",
"updatedAt": "2024-05-29T10:15:33.441Z"
}
],
"metadata": {
"pagination": {
"page": 1,
"limit": 20,
"total": 2,
"totalPages": 1,
"hasNext": false,
"hasPrev": false
}
}
}
Error Responses:
When an unexpected error occurs (database connection issues, invalid filter syntax, etc.):
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to find users"
}
}
4. Update User
Updates an existing user with partial data.
Request:
- Method:
PATCH - Path:
/users/:profileId - Headers:
Content-Type: application/jsonAuthorization: Bearer <token>x-nb-fingerprint: <device-fingerprint>
- Authorization: Bearer token required (admin or profile owner)
URL Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
profileId | string | ✅ | Unique user profile identifier |
Request Body (required, all fields optional):
| Field | Type | Required | Description |
|---|---|---|---|
avatar | object or null | ❌ | User avatar metadata or null |
name | string | ❌ | User's display name |
Note: While all fields in the request body are optional, the request body itself is required and cannot be empty. Sending an empty body will result in a 400 error.
Response Body:
| Field | Type | Description |
|---|---|---|
id | string | Unique user identifier |
identityId | string | Linked identity identifier |
name | string | Updated user's display name |
avatar | object or null | Updated user avatar metadata or null |
createdAt | string | Creation timestamp |
updatedAt | string | Last update timestamp |
Validation:
- Schema Validation: Enforced automatically (only name and avatar allowed; no additional properties)
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or owner of the target profile
Example Request:
curl -X PATCH {{host}}/users/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{"name": "John Doe Updated"}'
Success Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"identityId": "811ff0a3-a26f-447b-b68a-dd83ea4000b9",
"name": "John Doe",
"avatar": null,
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T14:22:15.789Z"
}
Error Responses:
When request body is empty or missing:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Request body is required"
}
}
When no user exists with the provided ID:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "User profile not found"
}
}
When the update operation doesn't modify any data (no changes detected):
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Failed to update user"
}
}
When an unexpected error occurs (database connection issues, etc.):
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to update user"
}
}
5. Delete User
Permanently deletes a user from the system.
Request:
- Method:
DELETE - Path:
/users/:profileId - Headers:
Authorization: Bearer <token>x-nb-fingerprint: <device-fingerprint>
- Authorization: Bearer token required (admin or profile owner)
URL Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
profileId | string | ✅ | Unique user profile identifier |
Response Body:
| Field | Type | Description |
|---|---|---|
| No response body | - | Delete endpoint returns no response body on success |
Validation:
- Schema Validation: None (DELETE request)
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or owner of the target profile
Example Request:
curl -X DELETE {{host}}/users/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2 \
-H "Authorization: Bearer <access-token>"
Success Response:
HTTP/1.1 204 No Content
Error Responses:
When no user exists with the provided ID:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "User not found"
}
}
When an unexpected error occurs (database connection issues, etc.):
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to delete user"
}
}
6. Get Avatar Upload URL
Generates a pre-signed URL for securely uploading a user avatar image. Returns an object ID and a temporary signed URL.
Request:
- Method:
GET - Path:
/user-profiles/:profileId/avatar-upload-url - Headers:
Authorization: Bearer <token> - Authorization: Bearer token required (admin or profile owner)
URL Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
profileId | string | ✅ | Target user profile ID |
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
contentType | string | ✅ | Image MIME type (enum: image/jpeg, image/png, image/webp, image/gif, image/svg+xml, image/avif, image/bmp, image/x-icon, image/tiff, image/heif, image/heic) |
contentLength | number | ✅ | File size in bytes (max 10MB = 10,000,000) |
Response Body:
| Field | Type | Description |
|---|---|---|
objectId | string | Generated storage object ID for the avatar |
url | string | Pre-signed URL for uploading the file |
Validation:
- Schema Validation: Uses image upload schema (content type and size constraints)
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or owner of the target profile
Example Request:
curl "{{host}}/user-profiles/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/avatar-upload-url?contentType=image/jpeg&contentLength=524288" \
-H "Authorization: Bearer <access-token>"
Success Response:
{
"objectId": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"url": "https://storage.googleapis.com/bucket/avatars/...&X-Goog-Expires=900&X-Goog-Signature=..."
}
7. Find Profiles by Identity ID
Retrieves paginated user profiles associated with a specific identity ID, with automatic avatar URL normalization and self-access control.
Request:
- Method:
GET - Path:
/profiles/identities/:identityId - Headers:
Authorization: Bearer <token> - Authorization: Bearer token required (self-access only - users can only view their own profiles)
URL Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
identityId | string | ✅ | Target identity ID to retrieve profiles for |
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
page | number | ❌ | 1 | Page number for pagination (1-1000) |
limit | number | ❌ | 10 | Number of profiles per page (1-50) |
Response (200 - Success):
{
"data": [
{
"id": "profile-123",
"name": "John Doe",
"avatar": {
"url": "https://cdn.example.com/avatars/profile-123.jpg",
"type": "image/jpeg"
},
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
],
"metadata": {
"pagination": {
"hasNext": false,
"hasPrev": false,
"limit": 10,
"page": 1,
"total": 1,
"totalPages": 1
}
}
}
Error Responses:
401 Unauthorized: Missing or invalid authentication token403 Forbidden: Attempting to access profiles of another identity (self-access violation)500 Internal Server Error: Database or avatar processing errors
Use Cases:
- Mobile apps retrieving user profiles for the authenticated identity
- Web applications displaying user profile information
- Profile management interfaces showing associated profiles
8. Create Profile Follow
Creates a social follow relationship between two user profiles, allowing users to follow each other for social networking features.
Request:
- Method:
PUT - Path:
/profiles/:profileId/profile-follows/:followProfileId - Headers:
Authorization: Bearer <token> - Authorization: Bearer token required (admin or profile owner)
- Body: Empty (no request body required)
URL Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
profileId | string | ✅ | ID of the profile performing the follow |
followProfileId | string | ✅ | ID of the profile to be followed |
Response Body: Empty (204 No Content)
Validation:
- Schema Validation: Path parameter validation for profile IDs
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or owner of the source profile
- Both profiles must exist in the database
- Business Logic: Prevents duplicate follows of the same profile
Error Responses:
400 Bad Request: Invalid profile IDs or malformed request401 Unauthorized: Missing or invalid authentication token403 Forbidden: User lacks permission (not admin or profile owner)404 Not Found: One or both profiles don't exist409 Conflict: Profile is already being followed500 Internal Server Error: Database operation failed
Example Request:
curl -X PUT "{{host}}/profiles/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/profile-follows/f8c9b2a1-3d4e-5f6g-7h8i-9j0k1l2m3n4o5p" \
-H "Authorization: Bearer <access-token>"
Success Response:
HTTP/1.1 204 No Content
Duplicate Follow Response:
HTTP/1.1 409 Conflict
Content-Type: application/json
{
"status": 409,
"message": "Profile is already followed",
"code": "ProfileAlreadyFollowedBlockError"
}
Use Cases:
- Social networking features
- Content personalization based on followed profiles
- Building follower/following networks
- Community engagement tracking
9. Delete Profile Follow
Deletes a social follow relationship between two user profiles (unfollowing), allowing users to remove connections to other profiles.
Request:
- Method:
DELETE - Path:
/profiles/:profileId/profile-follows/:followProfileId - Headers:
Authorization: Bearer <token> - Authorization: Bearer token required (admin or profile owner)
- Body: Empty (no request body required)
URL Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
profileId | string | ✅ | ID of the profile performing the unfollow |
followProfileId | string | ✅ | ID of the profile to be unfollowed |
Response Body: Empty (204 No Content)
Validation:
- Schema Validation: Path parameter validation for profile IDs
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or owner of the source profile
- Both profiles must exist in the database
- Follow relationship must exist
- Business Logic: Returns appropriate error if follow relationship doesn't exist
Error Responses:
400 Bad Request: Invalid profile IDs or malformed request401 Unauthorized: Missing or invalid authentication token403 Forbidden: User lacks permission (not admin or profile owner)404 Not Found: Profile or follow relationship doesn't exist500 Internal Server Error: Database operation failed
Example Request:
curl -X DELETE "{{host}}/profiles/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/profile-follows/f8c9b2a1-3d4e-5f6g-7h8i-9j0k1l2m3n4o5p" \
-H "Authorization: Bearer <access-token>"
Success Response:
HTTP/1.1 204 No Content
Follow Not Found Response:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"status": 404,
"message": "Profile follow not found",
"code": "ProfileFollowNotFoundBlockError"
}
Use Cases:
- Social networking features - unfollowing users
- Relationship management - removing connections
- Privacy control - managing social connections
- Community engagement tracking
10. Get Profile Followers
Retrieves a paginated list of followers for a specific profile, with normalized avatar URLs.
Request:
- Method:
GET - Path:
/profiles/:profileId/followers - Headers:
Authorization: Bearer <token> - Authorization: Bearer token required (admin or profile owner)
- Body: Empty (no request body required)
URL Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
profileId | string | ✅ | ID of the profile to retrieve followers for |
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
page | number | ❌ | 1 | Page number for pagination (1-1000) |
limit | number | ❌ | 20 | Number of results per page (1-50) |
Response Body: JSON with paginated follower list and metadata
Response Structure:
{
"data": [
{
"id": "string",
"name": "string",
"avatar": {
"url": "string",
"type": "string"
}
}
],
"metadata": {
"pagination": {
"page": number,
"limit": number,
"total": number,
"totalPages": number
}
}
}
Validation:
- Schema Validation: Path parameter validation for profile ID
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or owner of the profile
- Profile must exist in the database
- Business Logic: Returns paginated list with avatar URL normalization
Error Responses:
400 Bad Request: Invalid profile ID or malformed request401 Unauthorized: Missing or invalid authentication token403 Forbidden: User lacks permission (not admin or profile owner)404 Not Found: Profile doesn't exist500 Internal Server Error: Database operation failed
Example Request:
curl -X GET "{{host}}/profiles/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/followers?page=1&limit=20" \
-H "Authorization: Bearer <access-token>"
Success Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"data": [
{
"id": "user-456",
"name": "John Doe",
"avatar": {
"url": "https://storage.example.com/avatars/avatar123.png",
"type": "image/png"
}
},
{
"id": "user-789",
"name": "Jane Smith",
"avatar": {
"url": "https://storage.example.com/avatars/avatar456.jpg",
"type": "image/jpeg"
}
}
],
"metadata": {
"pagination": {
"page": 1,
"limit": 20,
"total": 50,
"totalPages": 3
}
}
}
Profile Not Found Response:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"status": 404,
"message": "Profile not found",
"code": "ProfileNotFoundBlockError"
}
Use Cases:
- Social networking features - displaying follower lists
- Analytics - tracking follower counts and growth
- Relationship management - viewing and managing social connections
- Community engagement - follower-based content distribution
Key Features:
- Pagination: Efficient handling of large follower lists
- Avatar Normalization: Automatic conversion of storage references to accessible URLs
- Flexible Query: Customizable page size and page number
- Performance: Optimized MongoDB queries using $elemMatch operator
11. Create Organization Follow
Creates a social follow relationship between a user profile and an organization, allowing users to subscribe to organization updates.
Request:
- Method:
PUT - Path:
/profiles/:profileId/organization-follows/:followOrganizationId - Headers:
Authorization: Bearer <token> - Authorization: Bearer token required (admin or profile owner)
- Body: Empty (no request body required)
URL Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
profileId | string | ✅ | ID of the profile performing the follow |
followOrganizationId | string | ✅ | ID of the organization to be followed |
Response Body: Empty (204 No Content)
Validation:
- Schema Validation: Path parameter validation for profile and organization IDs
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or owner of the source profile
- Both profile and organization must exist in the database
- Organization must not already be followed
- Business Logic: Returns appropriate error if organization is already followed
Error Responses:
400 Bad Request: Invalid profile/organization IDs or malformed request401 Unauthorized: Missing or invalid authentication token403 Forbidden: User lacks permission (not admin or profile owner)404 Not Found: Profile or organization doesn't exist409 Conflict: Organization is already followed500 Internal Server Error: Database operation failed
Example Request:
curl -X PUT "{{host}}/profiles/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/organization-follows/org-abc-123" \
-H "Authorization: Bearer <access-token>"
Success Response:
HTTP/1.1 204 No Content
Organization Already Followed Response:
HTTP/1.1 409 Conflict
Content-Type: application/json
{
"status": 409,
"message": "Organization is already followed",
"code": "OrganizationAlreadyFollowedBlockError"
}
Profile/Organization Not Found Response:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"status": 404,
"message": "Profile not found",
"code": "ProfileNotFoundBlockError"
}
Use Cases:
- Social networking features - following organizations
- Relationship management - creating connections to organizations
- Content subscription - allowing users to subscribe to organization updates
- Community engagement - organization-based content distribution
Key Features:
- Duplicate Prevention: Prevents a profile from following the same organization multiple times
- Authorization: Ensures only authorized users can create follow relationships
- Validation: Comprehensive checks for profile and organization existence
- Performance: Efficient MongoDB operations for follow creation
12. Delete Organization Follow
Removes a social follow relationship between a user profile and an organization, allowing users to unsubscribe from organization updates.
Request:
- Method:
DELETE - Path:
/profiles/:profileId/organization-follows/:followOrganizationId - Headers:
Authorization: Bearer <token> - Authorization: Bearer token required (admin or profile owner)
- Body: Empty (no request body required)
URL Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
profileId | string | ✅ | ID of the profile removing the follow |
followOrganizationId | string | ✅ | ID of the organization to be unfollowed |
Response Body: Empty (204 No Content)
Validation:
- Schema Validation: Path parameter validation for profile and organization IDs
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or owner of the source profile
- Both profile and organization must exist in the database
- Organization follow relationship must exist to be deleted
- Business Logic: Returns 404 if follow relationship doesn't exist (not silent success)
Error Responses:
400 Bad Request: Invalid profile/organization IDs or malformed request401 Unauthorized: Missing or invalid authentication token403 Forbidden: User lacks permission (not admin or profile owner)404 Not Found: Profile, organization, or follow relationship doesn't exist500 Internal Server Error: Database operation failed
Example Request:
curl -X DELETE "{{host}}/profiles/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/organization-follows/org-abc-123" \
-H "Authorization: Bearer <access-token>"
Success Response:
HTTP/1.1 204 No Content
Organization Follow Not Found Response:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"status": 404,
"message": "Organization follow not found",
"code": "OrganizationFollowNotFoundBlockError"
}
Profile/Organization Not Found Response:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"status": 404,
"message": "Profile not found",
"code": "ProfileNotFoundBlockError"
}
Use Cases:
- Social networking features - unfollowing organizations
- Relationship management - removing connections to organizations
- Content subscription management - unsubscribing from organization updates
- Community engagement - dynamic organization relationship management
Key Features:
- Existence Validation: Returns 404 if follow relationship doesn't exist (prevents silent failures)
- Authorization: Ensures only authorized users can delete follow relationships
- Validation: Comprehensive checks for profile, organization, and follow relationship existence
- Performance: Efficient MongoDB $pull operation with existence check
13. Create Product Like
Creates a product like relationship for a user profile (favoriting a product).
Request:
- Method:
PUT - Path:
/profiles/:profileId/product-likes/:likeProductId - Headers:
Authorization: Bearer <access_token>x-nb-fingerprint: <device_fingerprint>
- Path Parameters:
profileId(string, required): ID of the profile that will like the productlikeProductId(string, required): ID of the product to be liked
- Body: Empty (no request body required)
Response:
Success (201 Created):
(Empty body)
Error Responses:
{
"error": {
"message": "Validation Error",
"data": [
"path parameter 'profileId' is required",
"path parameter 'likeProductId' is required"
]
},
"status": 400
}
{
"error": {
"message": "token could not be verified"
},
"status": 401
}
{
"error": {
"message": "Identity is not authorized to access this resource"
},
"status": 403
}
{
"error": {
"message": "Profile not found"
},
"status": 404,
"code": "ProfileNotFoundBlockError"
}
{
"error": {
"message": "Product not found"
},
"status": 404,
"code": "ProductNotFoundBlockError"
}
{
"error": {
"message": "Product is already liked"
},
"status": 409,
"code": "ProductAlreadyLikedBlockError"
}
{
"error": {
"message": "Failed to create product like"
},
"status": 500,
"code": "ProfileUnexpectedDBError"
}
Use Cases:
- Product engagement features - liking or favoriting products
- Wish list management - adding products to favorites
- Product recommendation - tracking user preferences
- E-commerce features - product interaction tracking
Key Features:
- Duplicate Prevention: Returns 409 if product is already liked (prevents duplicate entries)
- Authorization: Ensures only authorized users can create product likes
- Validation: Comprehensive checks for profile and product existence
- Performance: Efficient MongoDB $push operation with duplicate check using $ne operator
14. Delete Product Like
Deletes a product like relationship from a user profile (unfavoriting a product).
Request:
- Method:
DELETE - Path:
/profiles/:profileId/product-likes/:likeProductId - Headers:
Authorization: Bearer <access_token>x-nb-fingerprint: <device_fingerprint>
- Path Parameters:
profileId(string, required): ID of the profile that will unlike the productlikeProductId(string, required): ID of the product to be unliked
- Body: Empty (no request body required)
Response:
Success (204 No Content):
(Empty body)
Error Responses:
{
"error": {
"message": "Validation Error",
"data": [
"path parameter 'profileId' is required",
"path parameter 'likeProductId' is required"
]
},
"status": 400
}
{
"error": {
"message": "token could not be verified"
},
"status": 401
}
{
"error": {
"message": "Identity is not authorized to access this resource"
},
"status": 403
}
{
"error": {
"message": "Profile not found"
},
"status": 404,
"code": "ProfileNotFoundBlockError"
}
{
"error": {
"message": "Product not found"
},
"status": 404,
"code": "ProductNotFoundBlockError"
}
{
"error": {
"message": "Product like not found"
},
"status": 404,
"code": "ProductLikeNotFoundBlockError"
}
{
"error": {
"message": "Failed to delete product like"
},
"status": 500,
"code": "ProfileUnexpectedDBError"
}
Use Cases:
- Product engagement features - unliking or removing from favorites
- Wish list management - removing products from favorites
- Product recommendation - updating user preferences
- E-commerce features - managing product interactions
Key Features:
- Existence Validation: Returns 404 if like relationship doesn't exist (prevents silent failures)
- Authorization: Ensures only authorized users can delete product likes
- Validation: Comprehensive checks for profile, product, and like relationship existence
- Performance: Efficient MongoDB $pull operation with existence check
⚙️ Configuration Options
Service Configuration
interface UserServiceConfiguration {
authSecrets: {
authEncSecret: string; // JWT encryption secret
authSignSecret: string; // JWT signing secret
};
identity?: {
typeIds?: {
admin: string; // Admin user type identifier
guest: string; // Guest user type identifier
regular: string; // Regular user type identifier
};
};
}
Configuration Details
The user service configuration is organized into logical groups for security and user type management.
🔐 Security Settings
authSecrets - JWT token security secrets
- Type:
{ authEncSecret: string; authSignSecret: string } - Description: Secret keys for JWT encryption and signing (used for token validation)
- Required: Yes (for production)
- Child Properties:
authEncSecret: Secret key for JWT payload encryptionauthSignSecret: Secret key for JWT signature verification
👥 User Type Settings
identity.typeIds - User type identifier configuration
- Type:
{ admin?: string; guest?: string; regular?: string } - Description: Custom user type identifiers for role-based access control
- Default:
undefined(uses default type validation) - Child Properties:
admin: Admin user type identifier- Type:
string - Description: Custom identifier for admin users
- Use Case: Role-based access control for administrative operations
- Example:
"admin","administrator","superuser"
- Type:
guest: Guest user type identifier- Type:
string - Description: Custom identifier for guest users
- Use Case: Limited access for unauthenticated or temporary users
- Example:
"guest","visitor","anonymous"
- Type:
regular: Regular user type identifier- Type:
string - Description: Custom identifier for regular users
- Use Case: Standard user access permissions
- Example:
"user","member","customer"
- Type:
Example Configuration
const userConfig = {
authSecrets: {
authEncSecret: process.env.AUTH_ENC_SECRET || 'your-enc-secret',
authSignSecret: process.env.AUTH_SIGN_SECRET || 'your-sign-secret'
},
identity: {
typeIds: {
admin: '100',
guest: '000',
regular: '001'
}
}
};
🚨 Error Handling
All user service errors return JSON format with appropriate HTTP status codes:
Common Error Codes
| Status | Error Message | Description |
|---|---|---|
| 400 | Validation Error | Invalid request body format or missing required fields |
| 400 | Failed to create user | Database insert operation failed to return an inserted ID |
| 400 | Failed to update user | Update operation doesn't modify any data (no changes detected) |
| 401 | token could not be verified | Missing or invalid authorization token |
| 403 | Identity is not authorized to access this resource | Insufficient permissions |
| 403 | User is not authorized to access this resource | User lacks required permissions (admin access) |
| 404 | User profile not found | User doesn't exist for GET/PATCH operations |
| 404 | User not found | User doesn't exist for DELETE operations |
| 500 | Failed to create user | Database connection issues or unexpected failures during creation |
| 500 | Failed to get user | Database connection issues or unexpected failures during retrieval |
| 500 | Failed to find users | Database connection issues, invalid filter syntax, or unexpected failures during listing |
| 500 | Failed to update user | Database connection issues or unexpected failures during update |
| 500 | Failed to delete user | Database connection issues or unexpected failures during deletion |
Error Response Format
{
"error": {
"message": "Error message description",
"data": ["Additional error details"]
}
}
Validation Errors include additional details:
{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'identityId'",
"request body must have required property 'name'"
]
}
}
🔗 Related Documentation
- Error Handling - Understanding error patterns
- Schema Component - Data validation concepts
- Custom Service Tutorial - Build your own services