9119e2383e
- Introduced a new `config.yaml` file for managing server, database, cache, queue, AI, scraping, logging, and rate limiting configurations. - Updated `docker-compose.yml` to reflect the new server port (8081) and adjusted health check endpoints accordingly. - Modified `Dockerfile` to expose the new server port. - Updated `README.md` to reflect changes in server configuration and added documentation for the new configuration structure. - Added test scripts for server and Swagger documentation testing. - Refactored customer domain structure to align with new configuration settings and improve maintainability.
554 lines
15 KiB
Markdown
554 lines
15 KiB
Markdown
# Customer Management Module
|
|
|
|
This module implements a complete User Management system for the Tender Management System, allowing administrators to register users who can later access the mobile application.
|
|
|
|
## Features
|
|
|
|
### 1. User Registration (by Admin)
|
|
- **Fields**: Full name, username, email, mobile number, password (hashed), national ID (optional), gender (enum), birthdate (optional), profile image (optional), user status (active/inactive), registration date
|
|
- **Uniqueness**: Ensures uniqueness for email, mobile, and username
|
|
- **Validation**: Comprehensive input validation using govalidator
|
|
|
|
### 2. Authentication for Mobile Users
|
|
- **Login**: Secure login via email or mobile number + password
|
|
- **JWT Tokens**: Access and refresh token generation
|
|
- **Password Security**: bcrypt hashing for secure password storage
|
|
|
|
### 3. Device Token Management
|
|
- **Storage**: Saves device_token and device_type (Android/iOS) when user logs in
|
|
- **Updates**: Updates token if user logs in from new device or re-installs app
|
|
- **Cleanup**: Endpoint to delete token on logout
|
|
|
|
### 4. User Profile Management
|
|
- **View/Edit**: Personal info (name, email, mobile, etc.)
|
|
- **Password Change**: Secure password change endpoint
|
|
- **Profile Picture**: Upload/update profile picture support
|
|
|
|
### 5. Push Notification Ready
|
|
- **Multiple Tokens**: Stores multiple device tokens per user
|
|
- **User Association**: Tokens tied to correct user ID
|
|
- **Admin Access**: API to get all active device tokens for admin push campaigns
|
|
|
|
### 6. Admin Panel APIs
|
|
- **List/Search/Filter**: Users by name, mobile, email, registration date, and status
|
|
- **Status Management**: Activate/deactivate users
|
|
- **Role Support**: Framework for role assignment (user, moderator, etc.)
|
|
|
|
### 7. Security & Best Practices
|
|
- **Input Validation**: Comprehensive validation and sanitization
|
|
- **Rate Limiting**: Framework for authentication endpoint rate limiting
|
|
- **Password Security**: bcrypt hashing with configurable cost
|
|
- **HTTP Status Codes**: Proper status codes and error messages
|
|
- **Activity Logging**: User activities (login, logout, profile update)
|
|
|
|
## Architecture
|
|
|
|
### Clean Architecture Implementation
|
|
- **Domain Layer**: Business entities, aggregates, interfaces, and core business rules
|
|
- **Service Layer**: Business logic and use cases
|
|
- **Handler Layer**: HTTP controllers and request/response handling
|
|
- **Repository Layer**: Data access implementations
|
|
- **Infrastructure Layer**: External dependencies (DB, cache, queues, config)
|
|
|
|
### File Structure
|
|
```
|
|
internal/customer/
|
|
├── entity.go # Core domain entities and types
|
|
├── form.go # Request/response forms with validation
|
|
├── repository.go # Repository interface and implementation
|
|
├── service.go # Business logic and use cases
|
|
├── handler.go # HTTP controllers and request/response handling
|
|
├── validation.go # Custom validation rules
|
|
└── README.md # This documentation
|
|
```
|
|
|
|
## Database Schema
|
|
|
|
### Customer Collection
|
|
```javascript
|
|
{
|
|
"_id": "uuid",
|
|
"full_name": "string",
|
|
"username": "string (unique)",
|
|
"email": "string (unique)",
|
|
"mobile": "string (unique)",
|
|
"password": "string (hashed)",
|
|
"national_id": "string (optional)",
|
|
"gender": "enum (male|female|other) (optional)",
|
|
"birthdate": "int64 (unix timestamp) (optional)",
|
|
"profile_image": "string (url) (optional)",
|
|
"status": "enum (active|inactive)",
|
|
"company_id": "uuid (optional)",
|
|
"is_verified": "boolean",
|
|
"device_tokens": [
|
|
{
|
|
"token": "string",
|
|
"device_type": "enum (android|ios)",
|
|
"created_at": "int64 (unix timestamp)",
|
|
"updated_at": "int64 (unix timestamp)"
|
|
}
|
|
],
|
|
"last_login_at": "int64 (unix timestamp) (optional)",
|
|
"created_at": "int64 (unix timestamp)",
|
|
"updated_at": "int64 (unix timestamp)"
|
|
}
|
|
```
|
|
|
|
### Indexes
|
|
- `email` (unique)
|
|
- `username` (unique)
|
|
- `mobile` (unique)
|
|
- `company_id`
|
|
- `status`
|
|
- `gender`
|
|
- `created_at` (descending)
|
|
- Text index on `full_name`, `email`, `mobile`, `username`
|
|
|
|
## API Endpoints
|
|
|
|
### Public Endpoints (No Authentication Required)
|
|
|
|
#### 1. Register Customer
|
|
```http
|
|
POST /api/customers/register
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"full_name": "John Doe",
|
|
"username": "johndoe",
|
|
"email": "john@example.com",
|
|
"mobile": "+1234567890",
|
|
"password": "securepassword123",
|
|
"national_id": "123456789",
|
|
"gender": "male",
|
|
"birthdate": 631152000,
|
|
"profile_image": "https://example.com/avatar.jpg",
|
|
"company_id": "uuid-optional"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Customer registered successfully",
|
|
"data": {
|
|
"id": "uuid",
|
|
"full_name": "John Doe",
|
|
"username": "johndoe",
|
|
"email": "john@example.com",
|
|
"mobile": "+1234567890",
|
|
"national_id": "123456789",
|
|
"gender": "male",
|
|
"birthdate": 631152000,
|
|
"profile_image": "https://example.com/avatar.jpg",
|
|
"status": "active",
|
|
"company_id": "uuid",
|
|
"is_verified": false,
|
|
"device_tokens": [],
|
|
"created_at": 1703123456,
|
|
"updated_at": 1703123456
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 2. Login
|
|
```http
|
|
POST /api/customers/login
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"email_or_mobile": "john@example.com",
|
|
"password": "securepassword123"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Login successful",
|
|
"data": {
|
|
"customer": {
|
|
"id": "uuid",
|
|
"full_name": "John Doe",
|
|
"username": "johndoe",
|
|
"email": "john@example.com",
|
|
"mobile": "+1234567890",
|
|
"status": "active",
|
|
"is_verified": false,
|
|
"device_tokens": [],
|
|
"last_login_at": 1703123456,
|
|
"created_at": 1703123456,
|
|
"updated_at": 1703123456
|
|
},
|
|
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
"refresh_token": "refresh_token_here",
|
|
"expires_at": 1703127056
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 3. Refresh Token
|
|
```http
|
|
POST /api/customers/refresh-token
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"refresh_token": "refresh_token_here"
|
|
}
|
|
```
|
|
|
|
### Protected Endpoints (Authentication Required)
|
|
|
|
#### 4. Get Profile
|
|
```http
|
|
GET /api/customers/profile
|
|
Authorization: Bearer <access_token>
|
|
X-Customer-ID: <customer_uuid>
|
|
```
|
|
|
|
#### 5. Update Profile
|
|
```http
|
|
PUT /api/customers/profile
|
|
Authorization: Bearer <access_token>
|
|
X-Customer-ID: <customer_uuid>
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"full_name": "John Updated Doe",
|
|
"email": "john.updated@example.com",
|
|
"mobile": "+1234567891",
|
|
"gender": "male",
|
|
"birthdate": 631152000,
|
|
"profile_image": "https://example.com/new-avatar.jpg"
|
|
}
|
|
```
|
|
|
|
#### 6. Change Password
|
|
```http
|
|
PUT /api/customers/change-password
|
|
Authorization: Bearer <access_token>
|
|
X-Customer-ID: <customer_uuid>
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"old_password": "currentpassword",
|
|
"new_password": "newsecurepassword123"
|
|
}
|
|
```
|
|
|
|
#### 7. Add Device Token
|
|
```http
|
|
POST /api/customers/device-token
|
|
Authorization: Bearer <access_token>
|
|
X-Customer-ID: <customer_uuid>
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"device_token": "fcm_token_here",
|
|
"device_type": "android"
|
|
}
|
|
```
|
|
|
|
#### 8. Remove Device Token
|
|
```http
|
|
DELETE /api/customers/device-token
|
|
Authorization: Bearer <access_token>
|
|
X-Customer-ID: <customer_uuid>
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"device_token": "fcm_token_here"
|
|
}
|
|
```
|
|
|
|
#### 9. Logout
|
|
```http
|
|
POST /api/customers/logout
|
|
Authorization: Bearer <access_token>
|
|
X-Customer-ID: <customer_uuid>
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"device_token": "fcm_token_here"
|
|
}
|
|
```
|
|
|
|
### Admin Endpoints (Admin Authentication Required)
|
|
|
|
#### 10. List Customers
|
|
```http
|
|
GET /api/admin/customers?search=john&status=active&gender=male&limit=20&offset=0&sort_by=created_at&sort_order=desc
|
|
Authorization: Bearer <admin_access_token>
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Customers retrieved successfully",
|
|
"data": [
|
|
{
|
|
"id": "uuid",
|
|
"full_name": "John Doe",
|
|
"username": "johndoe",
|
|
"email": "john@example.com",
|
|
"mobile": "+1234567890",
|
|
"status": "active",
|
|
"is_verified": false,
|
|
"device_tokens": [],
|
|
"last_login_at": 1703123456,
|
|
"created_at": 1703123456,
|
|
"updated_at": 1703123456
|
|
}
|
|
],
|
|
"meta": {
|
|
"total": 100,
|
|
"limit": 20,
|
|
"offset": 0,
|
|
"page": 1,
|
|
"pages": 5
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 11. Get Customer by ID
|
|
```http
|
|
GET /api/admin/customers/{customer_id}
|
|
Authorization: Bearer <admin_access_token>
|
|
```
|
|
|
|
#### 12. Update Customer Status
|
|
```http
|
|
PUT /api/admin/customers/{customer_id}/status
|
|
Authorization: Bearer <admin_access_token>
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"status": "inactive"
|
|
}
|
|
```
|
|
|
|
#### 13. Get All Device Tokens
|
|
```http
|
|
GET /api/admin/customers/device-tokens
|
|
Authorization: Bearer <admin_access_token>
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Device tokens retrieved successfully",
|
|
"data": [
|
|
{
|
|
"token": "fcm_token_1",
|
|
"device_type": "android",
|
|
"created_at": 1703123456,
|
|
"updated_at": 1703123456
|
|
},
|
|
{
|
|
"token": "fcm_token_2",
|
|
"device_type": "ios",
|
|
"created_at": 1703123457,
|
|
"updated_at": 1703123457
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## Validation Rules
|
|
|
|
### Registration Form
|
|
- `full_name`: Required, 2-100 characters
|
|
- `username`: Required, alphanumeric, 3-30 characters, unique
|
|
- `email`: Required, valid email format, unique
|
|
- `mobile`: Required, 10-15 characters, unique
|
|
- `password`: Required, 8-128 characters
|
|
- `national_id`: Optional, 5-20 characters
|
|
- `gender`: Optional, must be "male", "female", or "other"
|
|
- `birthdate`: Optional, valid Unix timestamp
|
|
- `profile_image`: Optional, valid URL
|
|
- `company_id`: Optional, valid UUID
|
|
|
|
### Login Form
|
|
- `email_or_mobile`: Required
|
|
- `password`: Required
|
|
|
|
### Update Form
|
|
- All fields optional with same validation rules as registration
|
|
- Uniqueness checks only if field is being updated
|
|
|
|
### Device Token Form
|
|
- `device_token`: Required, 32-255 characters
|
|
- `device_type`: Required, must be "android" or "ios"
|
|
|
|
### List Customers Form
|
|
- `search`: Optional, text search
|
|
- `status`: Optional, must be "active" or "inactive"
|
|
- `gender`: Optional, must be "male", "female", or "other"
|
|
- `company_id`: Optional, valid UUID
|
|
- `limit`: Optional, 1-100
|
|
- `offset`: Optional, minimum 0
|
|
- `sort_by`: Optional, must be "full_name", "email", "mobile", "created_at", or "last_login_at"
|
|
- `sort_order`: Optional, must be "asc" or "desc"
|
|
|
|
## Error Handling
|
|
|
|
### Standard Error Response Format
|
|
```json
|
|
{
|
|
"success": false,
|
|
"message": "Error message",
|
|
"error": {
|
|
"code": "ERROR_CODE",
|
|
"message": "Detailed error message",
|
|
"details": "Additional error details"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Common Error Codes
|
|
- `BAD_REQUEST`: Invalid request format or parameters
|
|
- `VALIDATION_ERROR`: Input validation failed
|
|
- `UNAUTHORIZED`: Authentication required or failed
|
|
- `FORBIDDEN`: Insufficient permissions
|
|
- `NOT_FOUND`: Resource not found
|
|
- `CONFLICT`: Resource already exists
|
|
- `INTERNAL_SERVER_ERROR`: Server error
|
|
|
|
### HTTP Status Codes
|
|
- `200 OK`: Success
|
|
- `201 Created`: Resource created successfully
|
|
- `400 Bad Request`: Invalid request
|
|
- `401 Unauthorized`: Authentication required
|
|
- `403 Forbidden`: Insufficient permissions
|
|
- `404 Not Found`: Resource not found
|
|
- `409 Conflict`: Resource conflict
|
|
- `422 Unprocessable Entity`: Validation error
|
|
- `500 Internal Server Error`: Server error
|
|
|
|
## Security Features
|
|
|
|
### Password Security
|
|
- bcrypt hashing with configurable cost
|
|
- Minimum 8 characters required
|
|
- Maximum 128 characters allowed
|
|
|
|
### Input Validation
|
|
- Comprehensive validation using govalidator
|
|
- Custom validators for Unix timestamps
|
|
- SQL injection prevention through parameterized queries
|
|
- XSS prevention through input sanitization
|
|
|
|
### Authentication
|
|
- JWT-based token system
|
|
- Access and refresh token separation
|
|
- Token expiration handling
|
|
- Secure token generation
|
|
|
|
### Data Protection
|
|
- Passwords never serialized in responses
|
|
- Sensitive data logging prevention
|
|
- Input sanitization and validation
|
|
|
|
## Usage Examples
|
|
|
|
### Register a New Customer (Admin)
|
|
```bash
|
|
curl -X POST http://localhost:8081/api/customers/register \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"full_name": "John Doe",
|
|
"username": "johndoe",
|
|
"email": "john@example.com",
|
|
"mobile": "+1234567890",
|
|
"password": "securepassword123",
|
|
"gender": "male",
|
|
"birthdate": 631152000
|
|
}'
|
|
```
|
|
|
|
### Login as Customer
|
|
```bash
|
|
curl -X POST http://localhost:8081/api/customers/login \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"email_or_mobile": "john@example.com",
|
|
"password": "securepassword123"
|
|
}'
|
|
```
|
|
|
|
### Update Profile
|
|
```bash
|
|
curl -X PUT http://localhost:8081/api/customers/profile \
|
|
-H "Content-Type: application/json" \
|
|
-H "Authorization: Bearer <access_token>" \
|
|
-H "X-Customer-ID: <customer_uuid>" \
|
|
-d '{
|
|
"full_name": "John Updated Doe",
|
|
"email": "john.updated@example.com"
|
|
}'
|
|
```
|
|
|
|
### List Customers (Admin)
|
|
```bash
|
|
curl -X GET "http://localhost:8081/api/admin/customers?search=john&status=active&limit=10" \
|
|
-H "Authorization: Bearer <admin_access_token>"
|
|
```
|
|
|
|
## Future Enhancements
|
|
|
|
### Planned Features
|
|
1. **JWT Implementation**: Proper JWT token generation and validation
|
|
2. **Email Verification**: Email verification system
|
|
3. **Password Reset**: Forgot password functionality
|
|
4. **Role-Based Access Control**: User roles and permissions
|
|
5. **Rate Limiting**: API rate limiting implementation
|
|
6. **Audit Logging**: Comprehensive audit trail
|
|
7. **Bulk Operations**: Bulk user import/export
|
|
8. **Advanced Search**: Full-text search with filters
|
|
9. **File Upload**: Profile picture upload handling
|
|
10. **Two-Factor Authentication**: 2FA support
|
|
|
|
### Technical Improvements
|
|
1. **Caching**: Redis caching for frequently accessed data
|
|
2. **Background Jobs**: Async processing for heavy operations
|
|
3. **Monitoring**: Health checks and metrics
|
|
4. **Testing**: Comprehensive unit and integration tests
|
|
5. **Documentation**: OpenAPI/Swagger documentation
|
|
6. **Performance**: Query optimization and indexing
|
|
7. **Security**: Additional security measures
|
|
8. **Scalability**: Horizontal scaling support
|
|
|
|
## Dependencies
|
|
|
|
### Required Packages
|
|
- `github.com/google/uuid`: UUID generation
|
|
- `github.com/labstack/echo/v4`: HTTP framework
|
|
- `github.com/asaskevich/govalidator`: Input validation
|
|
- `golang.org/x/crypto/bcrypt`: Password hashing
|
|
- `go.mongodb.org/mongo-driver`: MongoDB driver
|
|
|
|
### Configuration
|
|
- MongoDB connection string
|
|
- JWT secret key
|
|
- Password hashing cost
|
|
- Token expiration times
|
|
- Rate limiting settings
|
|
|
|
## Contributing
|
|
|
|
When contributing to this module:
|
|
|
|
1. Follow the existing code structure and patterns
|
|
2. Add comprehensive validation for new fields
|
|
3. Include proper error handling and logging
|
|
4. Write unit tests for new functionality
|
|
5. Update documentation for new endpoints
|
|
6. Follow security best practices
|
|
7. Use Unix timestamps for all time fields
|
|
8. Implement proper pagination for list endpoints
|
|
9. Add appropriate indexes for new fields
|
|
10. Follow the flat domain structure pattern |