@diagramers/api
Version:
Diagramers API - A comprehensive Node.js API template with TypeScript, Firebase Functions, and Socket.io
375 lines (366 loc) • 11.1 kB
text/typescript
import { Request, Response } from 'express';
import { Result } from '../../../shared/types/result';
import { ResponseCode } from '../../../shared/constants/enums';
import { handleResponse } from '../../../shared/utils/handle-response';
import { UserService } from '../services/user.service';
import { IUserCreate, IUserUpdate } from '../entities/user.entity';
export class UserController {
private userService: UserService;
constructor() {
this.userService = new UserService();
}
/**
* @openapi
* /api/users:
* get:
* summary: Get all users
* description: Retrieve a list of all active users
* tags: [Users]
* responses:
* 200:
* description: List of users retrieved successfully
* content:
* application/json:
* schema:
* type: object
* properties:
* Data:
* type: array
* items:
* $ref: '#/components/schemas/User'
* StatusCode:
* type: integer
* example: 1000
* 400:
* description: Bad request
*/
async getAll(req: Request, res: Response): Promise<void> {
try {
const result = await this.userService.getAll();
handleResponse(res, result);
} catch (error: any) {
handleResponse(res, Result.error('Failed to fetch users', error.message));
}
}
/**
* @openapi
* /api/users/{id}:
* get:
* summary: Get user by ID
* description: Retrieve a specific user by their ID
* tags: [Users]
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* description: User ID
* responses:
* 200:
* description: User retrieved successfully
* content:
* application/json:
* schema:
* type: object
* properties:
* Data:
* $ref: '#/components/schemas/User'
* StatusCode:
* type: integer
* example: 1000
* 404:
* description: User not found
*/
async getById(req: Request, res: Response): Promise<void> {
try {
const { id } = req.params;
const result = await this.userService.getById(id);
handleResponse(res, result);
} catch (error: any) {
handleResponse(res, Result.error('Failed to fetch user', error.message));
}
}
/**
* @openapi
* /api/users:
* post:
* summary: Create new user
* description: Create a new user account
* tags: [Users]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - email
* - username
* - password
* properties:
* email:
* type: string
* format: email
* username:
* type: string
* minLength: 3
* password:
* type: string
* minLength: 6
* firstName:
* type: string
* lastName:
* type: string
* phone:
* type: string
* role:
* type: string
* enum: [user, admin, moderator]
* responses:
* 201:
* description: User created successfully
* content:
* application/json:
* schema:
* type: object
* properties:
* Data:
* $ref: '#/components/schemas/User'
* StatusCode:
* type: integer
* example: 1000
* 409:
* description: User already exists
* 400:
* description: Bad request or missing required fields
*/
async create(req: Request, res: Response): Promise<void> {
try {
const userData: IUserCreate = req.body;
// Basic validation
if (!userData.email || !userData.username || !userData.password) {
handleResponse(res, Result.missingFields('Email, username, and password are required'));
return;
}
const result = await this.userService.create(userData);
handleResponse(res, result);
} catch (error: any) {
handleResponse(res, Result.error('Failed to create user', error.message));
}
}
/**
* @openapi
* /api/users/{id}:
* put:
* summary: Update user
* description: Update an existing user's information
* tags: [Users]
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* description: User ID
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* firstName:
* type: string
* lastName:
* type: string
* phone:
* type: string
* avatar:
* type: string
* isActive:
* type: boolean
* role:
* type: string
* enum: [user, admin, moderator]
* responses:
* 200:
* description: User updated successfully
* content:
* application/json:
* schema:
* type: object
* properties:
* Data:
* $ref: '#/components/schemas/User'
* StatusCode:
* type: integer
* example: 1000
* 404:
* description: User not found
*/
async update(req: Request, res: Response): Promise<void> {
try {
const { id } = req.params;
const userData: IUserUpdate = req.body;
const result = await this.userService.update(id, userData);
handleResponse(res, result);
} catch (error: any) {
handleResponse(res, Result.error('Failed to update user', error.message));
}
}
/**
* @openapi
* /api/users/{id}:
* delete:
* summary: Delete user
* description: Soft delete a user (sets status to 0)
* tags: [Users]
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* description: User ID
* responses:
* 200:
* description: User deleted successfully
* content:
* application/json:
* schema:
* type: object
* properties:
* Data:
* type: boolean
* example: true
* StatusCode:
* type: integer
* example: 1000
* 404:
* description: User not found
*/
async delete(req: Request, res: Response): Promise<void> {
try {
const { id } = req.params;
const result = await this.userService.delete(id);
handleResponse(res, result);
} catch (error: any) {
handleResponse(res, Result.error('Failed to delete user', error.message));
}
}
/**
* @openapi
* /api/users/profile:
* get:
* summary: Get user profile
* description: Get the current authenticated user's profile
* tags: [Users]
* security:
* - bearerAuth: []
* responses:
* 200:
* description: User profile retrieved successfully
* content:
* application/json:
* schema:
* type: object
* properties:
* Data:
* $ref: '#/components/schemas/User'
* StatusCode:
* type: integer
* example: 1000
* 401:
* description: User not authenticated
* 404:
* description: User not found
*/
async getProfile(req: Request, res: Response): Promise<void> {
try {
// Assuming user ID is available from auth middleware
const userId = (req as any).user?.id;
if (!userId) {
handleResponse(res, Result.unauthorized('User not authenticated'));
return;
}
const result = await this.userService.getById(userId);
handleResponse(res, result);
} catch (error: any) {
handleResponse(res, Result.error('Failed to fetch profile', error.message));
}
}
}
/**
* @openapi
* components:
* schemas:
* User:
* type: object
* properties:
* _id:
* type: string
* description: User ID
* email:
* type: string
* format: email
* description: User email address
* username:
* type: string
* description: Username
* firstName:
* type: string
* description: First name
* lastName:
* type: string
* description: Last name
* phone:
* type: string
* description: Phone number
* avatar:
* type: string
* description: Avatar URL
* isActive:
* type: boolean
* description: Whether user is active
* lastLoginAt:
* type: string
* format: date-time
* description: Last login timestamp
* emailVerified:
* type: boolean
* description: Whether email is verified
* phoneVerified:
* type: boolean
* description: Whether phone is verified
* role:
* type: string
* enum: [user, admin, moderator]
* description: User role
* permissions:
* type: array
* items:
* type: string
* description: User permissions
* status:
* type: integer
* description: User status (1 - active, 0 - deleted, -1 - suspended)
* createdAt:
* type: string
* format: date-time
* description: Creation timestamp
* updatedAt:
* type: string
* format: date-time
* description: Last update timestamp
* required:
* - email
* - username
* - isActive
* - emailVerified
* - phoneVerified
* - role
* - status
* - createdAt
* - updatedAt
*/