diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..a6929b8 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "StreamX", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/server/docs/swagger.js b/server/docs/swagger.js new file mode 100644 index 0000000..41d2671 --- /dev/null +++ b/server/docs/swagger.js @@ -0,0 +1,41 @@ +import swaggerJsDoc from 'swagger-jsdoc' +import swaggerUi from 'swagger-ui-express' + +const options = { + definition: { + openapi: '3.0.0', + info: { + title: 'StreamX API Documentation', + version: '1.0.0', + description: 'API documentation for StreamX application', + contact: { + name: 'StreamX Team', + }, + }, + servers: [ + { + url: 'http://localhost:3000', + description: 'Development server', + }, + ], + components: { + securitySchemes: { + bearerAuth: { + type: 'http', + scheme: 'bearer', + bearerFormat: 'JWT', + }, + }, + }, + security: [ + { + bearerAuth: [], + }, + ], + }, + apis: ['./routes/*.js', './controllers/*.js'], +} + +const specs = swaggerJsDoc(options) + +export { specs, swaggerUi } diff --git a/server/package.json b/server/package.json index b8c6aa5..b36b440 100644 --- a/server/package.json +++ b/server/package.json @@ -45,6 +45,8 @@ "passport-jwt": "^4.0.1", "path": "^0.12.7", "redis": "^5.0.0", + "swagger-jsdoc": "^6.2.8", + "swagger-ui-express": "^5.0.1", "jest": "^29.7.0", "morgan": "^1.10.0", "nodemon": "^3.1.4", diff --git a/server/routes/admin.route.js b/server/routes/admin.route.js index e55659d..467faf7 100644 --- a/server/routes/admin.route.js +++ b/server/routes/admin.route.js @@ -3,9 +3,100 @@ import { getAllEditors, getAllOwners, getAllRequests, getAllVideos } from '../co const router = express.Router() +/** + * @swagger + * /api/admin/owners: + * get: + * summary: Get all owners (admin access) + * tags: [Admin] + * security: + * - bearerAuth: [] + * responses: + * 200: + * description: List of all owners + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Owner' + * 401: + * description: Unauthorized - Admin access required + * 500: + * description: Server error + */ router.get('/owners', getAllOwners) + +/** + * @swagger + * /api/admin/editors: + * get: + * summary: Get all editors (admin access) + * tags: [Admin] + * security: + * - bearerAuth: [] + * responses: + * 200: + * description: List of all editors + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Editor' + * 401: + * description: Unauthorized - Admin access required + * 500: + * description: Server error + */ router.get('/editors', getAllEditors) + +/** + * @swagger + * /api/admin/requests: + * get: + * summary: Get all requests (admin access) + * tags: [Admin] + * security: + * - bearerAuth: [] + * responses: + * 200: + * description: List of all requests + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Request' + * 401: + * description: Unauthorized - Admin access required + * 500: + * description: Server error + */ router.get('/requests', getAllRequests) + +/** + * @swagger + * /api/admin/videos: + * get: + * summary: Get all videos (admin access) + * tags: [Admin] + * security: + * - bearerAuth: [] + * responses: + * 200: + * description: List of all videos + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Video' + * 401: + * description: Unauthorized - Admin access required + * 500: + * description: Server error + */ router.get('/videos', getAllVideos) export default router diff --git a/server/routes/auth0.route.js b/server/routes/auth0.route.js index 4e3402e..07f1ae4 100644 --- a/server/routes/auth0.route.js +++ b/server/routes/auth0.route.js @@ -2,6 +2,75 @@ import { Router } from 'express' import { auth0CreateController } from '../controllers/auth0.controller.js' const router = Router() +/** + * @swagger + * components: + * schemas: + * Auth0User: + * type: object + * properties: + * _id: + * type: string + * description: The auto-generated id of the Auth0 user + * auth0Id: + * type: string + * description: ID from Auth0 authentication + * email: + * type: string + * description: User's email address + * role: + * type: string + * enum: [owner, editor, admin] + * description: User's role in the system + * createdAt: + * type: string + * format: date-time + * description: When the user was created + * updatedAt: + * type: string + * format: date-time + * description: When the user was last updated + */ + +/** + * @swagger + * /auth0/create: + * post: + * summary: Create a new Auth0 user in the system + * tags: [Authentication] + * security: + * - bearerAuth: [] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * email: + * type: string + * description: User's email address + * role: + * type: string + * enum: [owner, editor, admin] + * description: User's role in the system + * required: + * - email + * - role + * responses: + * 201: + * description: Auth0 user created successfully + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Auth0User' + * 400: + * description: Invalid request data + * 401: + * description: Unauthorized - Invalid token + * 500: + * description: Server error + */ router.post('/create', auth0CreateController) export default router diff --git a/server/routes/editorGig.route.js b/server/routes/editorGig.route.js index 0ed9f53..44f3ec6 100644 --- a/server/routes/editorGig.route.js +++ b/server/routes/editorGig.route.js @@ -1,26 +1,246 @@ -import { Router } from 'express' +import express from 'express' import { createEditorGig, - getEditorGigByEmail, getEditorGigData, + getEditorGigByEmail, updateEditorGigByEmail, } from '../controllers/editorGig.controller.js' import { - getEditorGigPlans, - getEditorGigPlansByEmail, updateEditorGigPlans, + getEditorGigPlansByEmail, updateEditorGigPlansByEmail, + getEditorGigPlans, } from '../controllers/editorPlan.controller.js' -const router = Router() +const router = express.Router() + +/** + * @swagger + * components: + * schemas: + * EditorGig: + * type: object + * properties: + * _id: + * type: string + * description: The auto-generated id of the editor gig + * editorId: + * type: string + * description: ID of the editor + * title: + * type: string + * description: Title of the gig + * description: + * type: string + * description: Description of the gig + * price: + * type: number + * description: Price of the gig + * deliveryTime: + * type: number + * description: Delivery time in days + * revisions: + * type: number + * description: Number of revisions offered + * EditorGigPlan: + * type: object + * properties: + * _id: + * type: string + * description: The auto-generated id of the plan + * editorId: + * type: string + * description: ID of the editor + * basicTitle: + * type: string + * basicDescription: + * type: string + * basicPrice: + * type: number + * standardTitle: + * type: string + * standardDescription: + * type: string + * standardPrice: + * type: number + * premiumTitle: + * type: string + * premiumDescription: + * type: string + * premiumPrice: + * type: number + */ +/** + * @swagger + * /editor_gig: + * post: + * summary: Create a new editor gig + * tags: [Editor Gigs] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/EditorGig' + * responses: + * 201: + * description: Editor gig created successfully + * 400: + * description: Invalid request data + * 500: + * description: Server error + */ router.post('/', createEditorGig) + +/** + * @swagger + * /editor_gig: + * get: + * summary: Get all editor gigs + * tags: [Editor Gigs] + * responses: + * 200: + * description: List of all editor gigs + * 500: + * description: Server error + */ router.get('/', getEditorGigData) + +/** + * @swagger + * /editor_gig/plans: + * get: + * summary: Get all editor gig plans + * tags: [Editor Gigs] + * responses: + * 200: + * description: List of all editor gig plans + * 500: + * description: Server error + */ router.get('/plans', getEditorGigPlans) + +/** + * @swagger + * /editor_gig/plan: + * post: + * summary: Create editor gig plans + * tags: [Editor Gigs] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/EditorGigPlan' + * responses: + * 201: + * description: Editor gig plans created successfully + * 400: + * description: Invalid request data + * 500: + * description: Server error + */ router.post('/plan', updateEditorGigPlans) + +/** + * @swagger + * /editor_gig/email/{email}: + * get: + * summary: Get editor gig by email + * tags: [Editor Gigs] + * parameters: + * - in: path + * name: email + * required: true + * schema: + * type: string + * responses: + * 200: + * description: Editor gig details + * 404: + * description: Editor gig not found + * 500: + * description: Server error + */ router.get('/email/:email', getEditorGigByEmail) + +/** + * @swagger + * /editor_gig/plans/email/{email}: + * get: + * summary: Get editor gig plans by email + * tags: [Editor Gigs] + * parameters: + * - in: path + * name: email + * required: true + * schema: + * type: string + * responses: + * 200: + * description: Editor gig plans + * 404: + * description: Editor gig plans not found + * 500: + * description: Server error + */ router.get('/plans/email/:email', getEditorGigPlansByEmail) + +/** + * @swagger + * /editor_gig/email/{email}: + * patch: + * summary: Update editor gig by email + * tags: [Editor Gigs] + * parameters: + * - in: path + * name: email + * required: true + * schema: + * type: string + * requestBody: + * required: true + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/EditorGig' + * responses: + * 200: + * description: Editor gig updated successfully + * 404: + * description: Editor gig not found + * 500: + * description: Server error + */ router.patch('/email/:email', updateEditorGigByEmail) + +/** + * @swagger + * /editor_gig/plans/email/{email}: + * patch: + * summary: Update editor gig plans by email + * tags: [Editor Gigs] + * parameters: + * - in: path + * name: email + * required: true + * schema: + * type: string + * requestBody: + * required: true + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/EditorGigPlan' + * responses: + * 200: + * description: Editor gig plans updated successfully + * 404: + * description: Editor gig plans not found + * 500: + * description: Server error + */ router.patch('/plans/email/:email', updateEditorGigPlansByEmail) export default router diff --git a/server/routes/editorProfile.route.js b/server/routes/editorProfile.route.js index 8375727..eef6e36 100644 --- a/server/routes/editorProfile.route.js +++ b/server/routes/editorProfile.route.js @@ -1,21 +1,278 @@ -import { Router } from 'express' - +import express from 'express' import { createEditorProfile, - deleteEditorByEmail, - getEditorByEmail, getEditorNameById, getHiredByOwners, + deleteEditorByEmail, updateEditor, + getEditorByEmail, } from '../controllers/editorProfile.controller.js' +import { getAllEditors } from '../controllers/admin.controller.js' + +const router = express.Router() -const router = Router() +/** + * @swagger + * components: + * schemas: + * Editor: + * type: object + * properties: + * _id: + * type: string + * description: The auto-generated id of the editor + * email: + * type: string + * description: Editor's email address + * name: + * type: string + * description: Editor's name + * profilephoto: + * type: string + * description: URL to editor's profile photo + * bio: + * type: string + * description: Editor's biography + * experience: + * type: number + * description: Years of experience + * area_of_expertise: + * type: array + * items: + * type: string + * description: List of areas of expertise + * createdAt: + * type: string + * format: date-time + * description: When the editor account was created + * updatedAt: + * type: string + * format: date-time + * description: When the editor account was last updated + */ +/** + * @swagger + * /editorProfile: + * post: + * summary: Create a new editor profile + * tags: [Editors] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * email: + * type: string + * description: Editor's email address + * name: + * type: string + * description: Editor's name + * bio: + * type: string + * description: Editor's biography + * profilephoto: + * type: string + * description: URL to editor's profile photo + * experience: + * type: number + * description: Years of experience + * area_of_expertise: + * type: array + * items: + * type: string + * description: List of areas of expertise + * required: + * - email + * - name + * responses: + * 201: + * description: Editor profile created successfully + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Editor' + * 400: + * description: Invalid request data + * 500: + * description: Server error + */ router.post('/', createEditorProfile) + +/** + * @swagger + * /editorProfile: + * get: + * summary: Get all editor profiles + * tags: [Editors] + * responses: + * 200: + * description: List of all editor profiles + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Editor' + * 500: + * description: Server error + */ +router.get('/', getAllEditors) + +/** + * @swagger + * /editorProfile/name/{editorId}: + * get: + * summary: Get editor's name by ID + * tags: [Editors] + * parameters: + * - in: path + * name: editorId + * required: true + * schema: + * type: string + * description: Editor ID + * responses: + * 200: + * description: Editor's name + * content: + * application/json: + * schema: + * type: object + * properties: + * name: + * type: string + * 404: + * description: Editor not found + * 500: + * description: Server error + */ router.get('/name/:editorId', getEditorNameById) + +/** + * @swagger + * /editorProfile/{email}: + * get: + * summary: Get editor by email + * tags: [Editors] + * parameters: + * - in: path + * name: email + * required: true + * schema: + * type: string + * description: Editor's email address + * responses: + * 200: + * description: Editor details + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Editor' + * 404: + * description: Editor not found + * 500: + * description: Server error + */ router.get('/:email', getEditorByEmail) + +/** + * @swagger + * /editorProfile/{email}: + * put: + * summary: Update editor profile + * tags: [Editors] + * parameters: + * - in: path + * name: email + * required: true + * schema: + * type: string + * description: Editor's email address + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * name: + * type: string + * description: Updated name + * bio: + * type: string + * description: Updated biography + * profilephoto: + * type: string + * description: Updated profile photo URL + * experience: + * type: number + * description: Updated years of experience + * area_of_expertise: + * type: array + * items: + * type: string + * description: Updated areas of expertise + * responses: + * 200: + * description: Editor profile updated successfully + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Editor' + * 404: + * description: Editor not found + * 500: + * description: Server error + */ router.put('/:email', updateEditor) + +/** + * @swagger + * /editorProfile/{email}: + * delete: + * summary: Delete editor profile + * tags: [Editors] + * parameters: + * - in: path + * name: email + * required: true + * schema: + * type: string + * description: Editor's email address + * responses: + * 200: + * description: Editor profile deleted successfully + * 404: + * description: Editor not found + * 500: + * description: Server error + */ router.delete('/:email', deleteEditorByEmail) +/** + * @swagger + * /editorProfile/hiredby/{editorId}: + * get: + * summary: Get owners who hired this editor + * tags: [Editors] + * parameters: + * - in: path + * name: editorId + * required: true + * schema: + * type: string + * description: Editor ID + * responses: + * 200: + * description: List of owners who hired this editor + * 404: + * description: Editor not found + * 500: + * description: Server error + */ router.get('/hiredby/:editorId', getHiredByOwners) + export default router diff --git a/server/routes/owner.route.js b/server/routes/owner.route.js index b22e6aa..abc4791 100644 --- a/server/routes/owner.route.js +++ b/server/routes/owner.route.js @@ -14,22 +14,396 @@ import { upload } from '../middlewares/multer.middleware.js' const router = express.Router() -// Admin dashboard routes +/** + * @swagger + * components: + * schemas: + * Owner: + * type: object + * properties: + * _id: + * type: string + * description: The auto-generated id of the owner + * email: + * type: string + * description: Owner's email address + * username: + * type: string + * description: Owner's username + * profilephoto: + * type: string + * description: URL to owner's profile photo + * bio: + * type: string + * description: Owner's biography + * createdAt: + * type: string + * format: date-time + * description: When the owner account was created + * updatedAt: + * type: string + * format: date-time + * description: When the owner account was last updated + */ + +/** + * @swagger + * /api/ownerProfile: + * get: + * summary: Get all owners (admin access) + * tags: [Owners] + * responses: + * 200: + * description: List of all owners + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Owner' + * 500: + * description: Server error + */ router.get('/ownerProfile', getAllOwners) + +/** + * @swagger + * /api/ownerProfile/{email}: + * get: + * summary: Get owner by email + * tags: [Owners] + * parameters: + * - in: path + * name: email + * required: true + * schema: + * type: string + * description: Owner's email address + * responses: + * 200: + * description: Owner details + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Owner' + * 404: + * description: Owner not found + * 500: + * description: Server error + */ router.get('/ownerProfile/:email', getOwnerByEmail) + +/** + * @swagger + * /api/ownerProfile: + * post: + * summary: Create a new owner + * tags: [Owners] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * email: + * type: string + * description: Owner's email address + * username: + * type: string + * description: Owner's username + * required: + * - email + * - username + * responses: + * 201: + * description: Owner created successfully + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Owner' + * 400: + * description: Invalid request data + * 500: + * description: Server error + */ router.post('/ownerProfile', createOwner) + +/** + * @swagger + * /api/ownerProfile/{email}: + * patch: + * summary: Update owner information + * tags: [Owners] + * parameters: + * - in: path + * name: email + * required: true + * schema: + * type: string + * description: Owner's email address + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * username: + * type: string + * description: Updated username + * bio: + * type: string + * description: Updated biography + * responses: + * 200: + * description: Owner updated successfully + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Owner' + * 404: + * description: Owner not found + * 500: + * description: Server error + */ router.patch('/ownerProfile/:email', updateOwner) + +/** + * @swagger + * /api/ownerProfile/{email}: + * delete: + * summary: Delete an owner + * tags: [Owners] + * parameters: + * - in: path + * name: email + * required: true + * schema: + * type: string + * description: Owner's email address + * responses: + * 200: + * description: Owner deleted successfully + * 404: + * description: Owner not found + * 500: + * description: Server error + */ router.delete('/ownerProfile/:email', deleteOwner) -// Original routes +/** + * @swagger + * /api/owner/profile/{id}: + * get: + * summary: Get owner profile by ID + * tags: [Owners] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * description: Owner ID + * responses: + * 200: + * description: Owner profile details + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Owner' + * 404: + * description: Owner not found + * 500: + * description: Server error + */ router.get('/owner/profile/:id', getOwnerProfile) + +/** + * @swagger + * /api/owner/profile/setup/{id}: + * post: + * summary: Create owner profile + * tags: [Owners] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * description: Owner ID + * requestBody: + * required: true + * content: + * multipart/form-data: + * schema: + * type: object + * properties: + * file: + * type: string + * format: binary + * description: Profile photo + * firstName: + * type: string + * lastName: + * type: string + * bio: + * type: string + * responses: + * 201: + * description: Owner profile created successfully + * 400: + * description: Invalid request data + * 500: + * description: Server error + */ router.post('/owner/profile/setup/:id', upload.single('file'), createOwnerProfile) + +/** + * @swagger + * /api/owner/profile/settings/{id}: + * put: + * summary: Update owner profile settings + * tags: [Owners] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * description: Owner ID + * requestBody: + * required: true + * content: + * multipart/form-data: + * schema: + * type: object + * properties: + * file: + * type: string + * format: binary + * description: Updated profile photo + * firstName: + * type: string + * lastName: + * type: string + * bio: + * type: string + * responses: + * 200: + * description: Owner profile updated successfully + * 404: + * description: Owner not found + * 500: + * description: Server error + */ router.put('/owner/profile/settings/:id', upload.single('file'), updateOwnerProfile) -// New route for updating basic profile info +/** + * @swagger + * /api/owner/profile/basic/{id}: + * patch: + * summary: Update owner's basic profile information + * tags: [Owners] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * description: Owner ID + * requestBody: + * required: true + * content: + * multipart/form-data: + * schema: + * type: object + * properties: + * file: + * type: string + * format: binary + * description: Profile photo + * firstName: + * type: string + * lastName: + * type: string + * responses: + * 200: + * description: Basic profile updated successfully + * 404: + * description: Owner not found + * 500: + * description: Server error + */ router.patch('/owner/profile/basic/:id', upload.single('file'), updateBasicProfile) +/** + * @swagger + * /api/hired-editors/{ownerId}: + * get: + * summary: Get all editors hired by an owner + * tags: [Owners] + * parameters: + * - in: path + * name: ownerId + * required: true + * schema: + * type: string + * description: Owner ID + * responses: + * 200: + * description: List of hired editors + * content: + * application/json: + * schema: + * type: array + * items: + * type: object + * properties: + * editorId: + * type: string + * description: Editor ID + * username: + * type: string + * description: Editor username + * profilephoto: + * type: string + * description: URL to editor's profile photo + * 404: + * description: Owner not found + * 500: + * description: Server error + */ router.get('/hired-editors/:ownerId', getHiredEditors) + +/** + * @swagger + * /api/owner/name/{id}: + * get: + * summary: Get owner's name by ID + * tags: [Owners] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * description: Owner ID + * responses: + * 200: + * description: Owner's name + * content: + * application/json: + * schema: + * type: object + * properties: + * username: + * type: string + * 404: + * description: Owner not found + * 500: + * description: Server error + */ router.get('/owner/name/:id', getOwnerNameById) export default router diff --git a/server/routes/request.route.js b/server/routes/request.route.js index bca1ddd..1d7ecba 100644 --- a/server/routes/request.route.js +++ b/server/routes/request.route.js @@ -11,30 +11,452 @@ import { getRequestsByToId, updateRequestStatus, } from '../controllers/request.controller.js' +import { getAllRequests } from '../controllers/admin.controller.js' const router = express.Router() -// Create a new request +/** + * @swagger + * components: + * schemas: + * Request: + * type: object + * properties: + * _id: + * type: string + * description: The auto-generated id of the request + * from_id: + * type: string + * description: ID of the user who created the request + * to_id: + * type: string + * description: ID of the user who received the request + * status: + * type: string + * enum: [pending, accepted, rejected, completed] + * description: Current status of the request + * description: + * type: string + * description: Description of the request + * price: + * type: number + * description: Price or budget for the request + * createdAt: + * type: string + * format: date-time + * description: When the request was created + * updatedAt: + * type: string + * format: date-time + * description: When the request was last updated + * RequestMessage: + * type: object + * properties: + * _id: + * type: string + * description: The auto-generated id of the message + * requestId: + * type: string + * description: ID of the request this message belongs to + * senderId: + * type: string + * description: ID of the user who sent the message + * content: + * type: string + * description: Content of the message + * createdAt: + * type: string + * format: date-time + * description: When the message was created + */ + +/** + * @swagger + * /requests/create: + * post: + * summary: Create a new request + * tags: [Requests] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * from_id: + * type: string + * description: ID of the user creating the request + * to_id: + * type: string + * description: ID of the user receiving the request + * description: + * type: string + * description: Description of the request + * price: + * type: number + * description: Price or budget for the request + * required: + * - from_id + * - to_id + * - description + * responses: + * 201: + * description: Request created successfully + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Request' + * 400: + * description: Invalid request data + * 500: + * description: Server error + */ router.post('/create', createRequest) -// Get requests by owner/editor ID +/** + * @swagger + * /requests: + * get: + * summary: Get all requests + * tags: [Requests] + * responses: + * 200: + * description: List of all requests + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Request' + * 500: + * description: Server error + */ +router.get('/', getAllRequests) + +/** + * @swagger + * /requests/all: + * get: + * summary: Get all updated requests + * tags: [Requests] + * responses: + * 200: + * description: List of all updated requests + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Request' + * 500: + * description: Server error + */ +router.get('/all', getAllRequests) + +/** + * @swagger + * /requests/to-id/{to_id}: + * get: + * summary: Get requests by recipient ID + * tags: [Requests] + * parameters: + * - in: path + * name: to_id + * required: true + * schema: + * type: string + * description: ID of request recipient + * responses: + * 200: + * description: List of requests sent to the specified user + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Request' + * 500: + * description: Server error + */ router.get('/to-id/:to_id', getRequestsByToId) -// Get requests by owner/editor ID +/** + * @swagger + * /requests/from-id/{from_id}: + * get: + * summary: Get requests by sender ID + * tags: [Requests] + * parameters: + * - in: path + * name: from_id + * required: true + * schema: + * type: string + * description: ID of request sender + * responses: + * 200: + * description: List of requests sent by the specified user + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Request' + * 500: + * description: Server error + */ router.get('/from-id/:from_id', getRequestsByFromId) -// Update request status +/** + * @swagger + * /requests/admin: + * get: + * summary: Get admin requests + * tags: [Requests] + * responses: + * 200: + * description: List of admin requests + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Request' + * 500: + * description: Server error + */ +router.get('/admin', getAllRequests) + +/** + * @swagger + * /requests/{id}/status: + * patch: + * summary: Update request status + * tags: [Requests] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * description: Request ID + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * status: + * type: string + * enum: [pending, accepted, rejected, completed] + * description: New status for the request + * required: + * - status + * responses: + * 200: + * description: Request status updated successfully + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Request' + * 400: + * description: Invalid status value + * 404: + * description: Request not found + * 500: + * description: Server error + */ router.patch('/:id/status', updateRequestStatus) +/** + * @swagger + * /requests/delete/{id}: + * delete: + * summary: Delete a request + * tags: [Requests] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * description: Request ID to delete + * responses: + * 200: + * description: Request deleted successfully + * 404: + * description: Request not found + * 500: + * description: Server error + */ router.delete('/delete/:id', deleteRequest) +/** + * @swagger + * /requests/aggregate/{fromId}: + * get: + * summary: Get aggregated request data for a user + * tags: [Requests] + * parameters: + * - in: path + * name: fromId + * required: true + * schema: + * type: string + * description: User ID to aggregate requests for + * responses: + * 200: + * description: Aggregated request data + * 500: + * description: Server error + */ router.get('/aggregate/:fromId', aggregateRequestsController) -// Message thread routes +/** + * @swagger + * /requests/{id}/messages: + * get: + * summary: Get messages for a specific request + * tags: [Requests] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * description: Request ID + * responses: + * 200: + * description: List of request messages + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/RequestMessage' + * 404: + * description: Request not found + * 500: + * description: Server error + */ router.get('/:id/messages', getRequestMessages) + +/** + * @swagger + * /requests/{id}/messages: + * post: + * summary: Add a message to a request + * tags: [Requests] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * description: Request ID + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * senderId: + * type: string + * description: ID of the user sending the message + * content: + * type: string + * description: Message content + * required: + * - senderId + * - content + * responses: + * 201: + * description: Message added successfully + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/RequestMessage' + * 400: + * description: Invalid message data + * 404: + * description: Request not found + * 500: + * description: Server error + */ router.post('/:id/messages', addMessageToRequest) +/** + * @swagger + * /requests/from-to: + * post: + * summary: Get requests between two users + * tags: [Requests] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * fromId: + * type: string + * description: ID of the sender + * toId: + * type: string + * description: ID of the receiver + * required: + * - fromId + * - toId + * responses: + * 200: + * description: List of requests between specified users + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Request' + * 500: + * description: Server error + */ router.post('/from-to', getRequestsByFromToId) + +/** + * @swagger + * /requests/change-price: + * post: + * summary: Change the price of a request + * tags: [Requests] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * requestId: + * type: string + * description: ID of the request + * price: + * type: number + * description: New price + * required: + * - requestId + * - price + * responses: + * 200: + * description: Request price updated successfully + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Request' + * 404: + * description: Request not found + * 500: + * description: Server error + */ router.post('/change-price', changePrice) export default router diff --git a/server/routes/user.route.js b/server/routes/user.route.js index f90fc49..dd4db2d 100644 --- a/server/routes/user.route.js +++ b/server/routes/user.route.js @@ -2,6 +2,75 @@ import express from 'express' import { createUser } from '../controllers/user.controller.js' const router = express.Router() +/** + * @swagger + * components: + * schemas: + * User: + * type: object + * properties: + * _id: + * type: string + * description: The auto-generated id of the user + * email: + * type: string + * description: User's email address + * auth0Id: + * type: string + * description: User's Auth0 ID + * role: + * type: string + * enum: [owner, editor, admin] + * description: User's role in the system + * createdAt: + * type: string + * format: date-time + * description: When the user was created + * updatedAt: + * type: string + * format: date-time + * description: When the user was last updated + */ + +/** + * @swagger + * /user: + * post: + * summary: Create a new user + * tags: [Users] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * email: + * type: string + * description: User's email address + * auth0Id: + * type: string + * description: User's Auth0 ID + * role: + * type: string + * enum: [owner, editor, admin] + * description: User's role in the system + * required: + * - email + * - auth0Id + * - role + * responses: + * 201: + * description: User created successfully + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/User' + * 400: + * description: Invalid request data + * 500: + * description: Server error + */ router.post('/', createUser) export default router diff --git a/server/routes/video.route.js b/server/routes/video.route.js index b1320d6..ecc6ee7 100644 --- a/server/routes/video.route.js +++ b/server/routes/video.route.js @@ -7,6 +7,7 @@ import { updateVideoOwnership, uploadController, } from '../controllers/video.controller.js' +import { getAllVideos } from '../controllers/admin.controller.js' import { upload } from '../middlewares/multer.middleware.js' const router = Router() @@ -23,14 +24,282 @@ const logRequest = (req, res, next) => { next() } +/** + * @swagger + * components: + * schemas: + * Video: + * type: object + * properties: + * _id: + * type: string + * description: The auto-generated id of the video + * ownerId: + * type: string + * description: ID of the video owner + * editorId: + * type: string + * description: ID of the assigned editor + * url: + * type: string + * description: URL of the video + * editorAccess: + * type: boolean + * description: Whether editor has access to this video + * metaData: + * type: object + * description: Metadata of the video + * createdAt: + * type: string + * format: date-time + * description: When the video was created + * updatedAt: + * type: string + * format: date-time + * description: When the video was last updated + */ + +/** + * @swagger + * /api/videos/all-videos: + * get: + * summary: Get all videos (admin access) + * tags: [Videos] + * responses: + * 200: + * description: List of all videos + * content: + * application/json: + * schema: + * type: object + * properties: + * videos: + * type: array + * items: + * $ref: '#/components/schemas/Video' + * 500: + * description: Server error + */ +router.get('/all-videos', getAllVideos) + +/** + * @swagger + * /api/videos/all/{role}/{userId}: + * get: + * summary: Get all videos for a user based on role + * tags: [Videos] + * parameters: + * - in: path + * name: role + * required: true + * schema: + * type: string + * enum: [Owner, Editor, Admin] + * description: User role + * - in: path + * name: userId + * required: true + * schema: + * type: string + * description: User ID + * responses: + * 200: + * description: List of videos + * content: + * application/json: + * schema: + * type: object + * properties: + * videos: + * type: array + * items: + * $ref: '#/components/schemas/Video' + * 400: + * description: Invalid role specified + * 500: + * description: Server error + */ router.get('/all/:role/:userId', getAllController) + +/** + * @swagger + * /api/videos/recent/{role}/{userId}: + * get: + * summary: Get recent videos for a user based on role + * tags: [Videos] + * parameters: + * - in: path + * name: role + * required: true + * schema: + * type: string + * enum: [Owner, Editor, Admin] + * description: User role + * - in: path + * name: userId + * required: true + * schema: + * type: string + * description: User ID + * responses: + * 200: + * description: List of recent videos + * content: + * application/json: + * schema: + * type: object + * properties: + * videos: + * type: array + * items: + * $ref: '#/components/schemas/Video' + * 400: + * description: Invalid role specified + * 500: + * description: Server error + */ router.get('/recent/:role/:userId', recentController) + +/** + * @swagger + * /api/videos/storage-usages/{role}/{userId}: + * get: + * summary: Get storage usage for a user based on role + * tags: [Videos] + * parameters: + * - in: path + * name: role + * required: true + * schema: + * type: string + * enum: [Owner, Editor, Admin] + * description: User role + * - in: path + * name: userId + * required: true + * schema: + * type: string + * description: User ID + * responses: + * 200: + * description: Storage usage information + * content: + * application/json: + * schema: + * type: object + * properties: + * totalSize: + * type: number + * description: Total storage used in bytes + * videoCount: + * type: number + * description: Number of videos + * 400: + * description: Invalid role specified + * 500: + * description: Server error + */ router.get('/storage-usages/:role/:userId', storageUsageController) +/** + * @swagger + * /api/videos/upload: + * post: + * summary: Upload a new video + * tags: [Videos] + * requestBody: + * required: true + * content: + * multipart/form-data: + * schema: + * type: object + * properties: + * file: + * type: string + * format: binary + * description: Video file to upload + * userId: + * type: string + * description: ID of the user uploading the video + * role: + * type: string + * enum: [Owner, Editor] + * description: Role of the user uploading + * responses: + * 200: + * description: Video uploaded successfully + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Video' + * 400: + * description: Invalid request or missing file + * 500: + * description: Server error during upload + */ router.post('/upload', upload.single('file'), uploadController) +/** + * @swagger + * /api/videos/update-ownership: + * patch: + * summary: Update video ownership + * tags: [Videos] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * videoId: + * type: string + * description: ID of the video to update + * ownerId: + * type: string + * description: New owner ID + * editorId: + * type: string + * description: New editor ID + * editorAccess: + * type: boolean + * description: Whether editor has access + * responses: + * 200: + * description: Video ownership updated successfully + * 400: + * description: Invalid request or missing data + * 500: + * description: Server error + */ router.patch('/update-ownership', updateVideoOwnership) +/** + * @swagger + * /api/videos/delete: + * delete: + * summary: Delete a video + * tags: [Videos] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * videoId: + * type: string + * description: ID of the video to delete + * responses: + * 200: + * description: Video deleted successfully + * 400: + * description: Invalid request or missing video ID + * 404: + * description: Video not found + * 500: + * description: Server error during deletion + */ router.delete('/delete', deleteController) //? Router-level middleware diff --git a/server/routes/wallet.route.js b/server/routes/wallet.route.js index 18b3add..f463863 100644 --- a/server/routes/wallet.route.js +++ b/server/routes/wallet.route.js @@ -10,25 +10,280 @@ import { const router = express.Router() -// Get all wallets (admin route) +/** + * @swagger + * components: + * schemas: + * Wallet: + * type: object + * properties: + * _id: + * type: string + * description: The auto-generated id of the wallet + * userId: + * type: string + * description: ID of the user who owns this wallet + * balance: + * type: number + * description: Current wallet balance + * type: + * type: string + * enum: [owner, editor, admin] + * description: Type of the wallet + * createdAt: + * type: string + * format: date-time + * description: When the wallet was created + * updatedAt: + * type: string + * format: date-time + * description: When the wallet was last updated + */ + +/** + * @swagger + * /api/wallet: + * get: + * summary: Get all wallets (admin access) + * tags: [Wallets] + * responses: + * 200: + * description: List of all wallets + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Wallet' + * 500: + * description: Server error + */ router.get('/', getAllWallets) -// Get wallet by ID +/** + * @swagger + * /api/wallet/{id}: + * get: + * summary: Get wallet by ID + * tags: [Wallets] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * description: Wallet ID + * responses: + * 200: + * description: Wallet details + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Wallet' + * 404: + * description: Wallet not found + * 500: + * description: Server error + */ router.get('/:id', getWallet) -// Create a new wallet +/** + * @swagger + * /api/wallet: + * post: + * summary: Create a new wallet + * tags: [Wallets] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * userId: + * type: string + * description: User ID for whom wallet is being created + * type: + * type: string + * enum: [owner, editor, admin] + * description: Type of wallet + * initialBalance: + * type: number + * description: Initial wallet balance + * required: + * - userId + * - type + * responses: + * 201: + * description: Wallet created successfully + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Wallet' + * 400: + * description: Invalid request data + * 500: + * description: Server error + */ router.post('/', createWallet) -// Update wallet balance (PATCH) +/** + * @swagger + * /api/wallet/{id}/balance: + * patch: + * summary: Update wallet balance + * tags: [Wallets] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * description: Wallet ID + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * amount: + * type: number + * description: Amount to add or subtract (use negative for withdrawal) + * required: + * - amount + * responses: + * 200: + * description: Wallet balance updated successfully + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Wallet' + * 400: + * description: Invalid request or insufficient funds + * 404: + * description: Wallet not found + * 500: + * description: Server error + */ router.patch('/:id/balance', updateBalance) -// Add money to wallet (POST) +/** + * @swagger + * /api/wallet/{id}/deposit: + * post: + * summary: Add money to wallet + * tags: [Wallets] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * description: Wallet ID + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * amount: + * type: number + * description: Amount to deposit + * required: + * - amount + * responses: + * 200: + * description: Money added to wallet + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Wallet' + * 400: + * description: Invalid request + * 404: + * description: Wallet not found + * 500: + * description: Server error + */ router.post('/:id/deposit', updateBalance) -// Transfer money between wallets +/** + * @swagger + * /api/wallet/transfer: + * post: + * summary: Transfer money between wallets + * tags: [Wallets] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * sourceWalletId: + * type: string + * description: Source wallet ID + * destinationWalletId: + * type: string + * description: Destination wallet ID + * amount: + * type: number + * description: Amount to transfer + * required: + * - sourceWalletId + * - destinationWalletId + * - amount + * responses: + * 200: + * description: Money transferred successfully + * content: + * application/json: + * schema: + * type: object + * properties: + * sourceWallet: + * $ref: '#/components/schemas/Wallet' + * destinationWallet: + * $ref: '#/components/schemas/Wallet' + * amount: + * type: number + * 400: + * description: Invalid request or insufficient funds + * 404: + * description: One or both wallets not found + * 500: + * description: Server error + */ router.post('/transfer', transferMoney) -// Get wallets by type +/** + * @swagger + * /api/wallet/type/{type}: + * get: + * summary: Get wallets by type + * tags: [Wallets] + * parameters: + * - in: path + * name: type + * required: true + * schema: + * type: string + * enum: [owner, editor, admin] + * description: Type of wallets to retrieve + * responses: + * 200: + * description: List of wallets by type + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Wallet' + * 500: + * description: Server error + */ router.get('/type/:type', getWalletsByType) export default router diff --git a/server/routes/yt.route.js b/server/routes/yt.route.js index b5a6863..101e301 100644 --- a/server/routes/yt.route.js +++ b/server/routes/yt.route.js @@ -2,7 +2,148 @@ import { Router } from 'express' import { reqAdminController, uploadController } from '../controllers/yt.controller.js' const router = Router() +/** + * @swagger + * components: + * schemas: + * YTUpload: + * type: object + * properties: + * _id: + * type: string + * description: The auto-generated id of the YouTube upload + * userId: + * type: string + * description: ID of the user who uploaded the video + * role: + * type: string + * enum: [Owner, Editor] + * description: Role of the user who uploaded + * videoId: + * type: string + * description: ID of the uploaded video + * youtubeLink: + * type: string + * description: Link to the YouTube video + * status: + * type: string + * description: Upload status + * createdAt: + * type: string + * format: date-time + * description: When the upload was created + * updatedAt: + * type: string + * format: date-time + * description: When the upload was last updated + */ + +/** + * @swagger + * /api/yt/upload/{role}/{userId}/{id}: + * post: + * summary: Upload a video to YouTube + * tags: [YouTube] + * parameters: + * - in: path + * name: role + * required: true + * schema: + * type: string + * enum: [Owner, Editor] + * description: Role of the user uploading + * - in: path + * name: userId + * required: true + * schema: + * type: string + * description: ID of the user uploading + * - in: path + * name: id + * required: true + * schema: + * type: string + * description: ID of the video to upload + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * title: + * type: string + * description: YouTube video title + * description: + * type: string + * description: YouTube video description + * tags: + * type: array + * items: + * type: string + * description: YouTube video tags + * categoryId: + * type: string + * description: YouTube category ID + * privacyStatus: + * type: string + * enum: [private, public, unlisted] + * description: Privacy status of the video + * required: + * - title + * - description + * responses: + * 200: + * description: Video uploaded to YouTube successfully + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/YTUpload' + * 400: + * description: Invalid request data + * 500: + * description: Server error during upload + */ router.post('/upload/:role/:userId/:id', uploadController) + +/** + * @swagger + * /api/yt/req-admin/{videoId}: + * post: + * summary: Request admin for YouTube upload + * tags: [YouTube] + * parameters: + * - in: path + * name: videoId + * required: true + * schema: + * type: string + * description: ID of the video for admin request + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * userId: + * type: string + * description: ID of the user making the request + * reason: + * type: string + * description: Reason for the admin request + * required: + * - userId + * responses: + * 200: + * description: Admin request submitted successfully + * 400: + * description: Invalid request data + * 404: + * description: Video not found + * 500: + * description: Server error + */ router.post('/req-admin/:videoId', reqAdminController) export default router diff --git a/server/tests/unit/controllers/ownerController.test.js b/server/tests/unit/controllers/ownerController.test.js index 6abcaa4..3bba60a 100644 --- a/server/tests/unit/controllers/ownerController.test.js +++ b/server/tests/unit/controllers/ownerController.test.js @@ -8,7 +8,7 @@ const mockOwnerModel = function () { } } -// Use variables to store the mock implementations +// Use variables to store the mock const mockCacheService = { generateKey: jest.fn(), get: jest.fn(),