diff --git a/server/src/controllers/admin.controller.js b/server/src/controllers/admin.controller.js new file mode 100644 index 0000000..8d12cc8 --- /dev/null +++ b/server/src/controllers/admin.controller.js @@ -0,0 +1,37 @@ +'use strict' + +const { StatusOrder } = require("../common/status") +const Order = require("../models/order.model") +const Tour = require("../models/tour.model") + +class AdminController { + getCustomerNumber = async (req, res, next) => { + try { + const totalBookedNumber = await Tour.sum("booked_number") + return res.status(200).json({ + message: "Get total booked number successfully!", + total: totalBookedNumber + }) + } catch (error) { + return res.status(500).json({ message: error.message }) + } + } + + getTotalRevenue = async (req, res, next) => { + try { + const totalRevenue = await Order.sum("total_to_pay", { + where: { + status: StatusOrder.COMPLETE + } + }) + return res.status(200).json({ + message: "Get total revenue successfully!", + total_revenue: totalRevenue + }) + } catch (error) { + return res.status(500).json({ message: error.message }) + } + } +} + +module.exports = new AdminController() \ No newline at end of file diff --git a/server/src/controllers/tour_guide.controller.js b/server/src/controllers/tour_guide.controller.js index b9af4d2..23f89fc 100644 --- a/server/src/controllers/tour_guide.controller.js +++ b/server/src/controllers/tour_guide.controller.js @@ -1,10 +1,13 @@ 'use strict' const { RoleUser } = require("../common/status"); +const { BadRequestError } = require("../core/error.response"); const GuideTour = require("../models/guide_tour.model"); const TourGuide = require("../models/tour_guide.model"); const { findTourById } = require("../services/tour.service") const bcrypt = require('bcrypt'); +const { isAdmin } = require("../middlewares/authenticate"); +const User = require("../models/user.model"); const role_user = { ADMIN: 'admin', @@ -95,6 +98,48 @@ class TourGuideController { throw new Error("Error: ", error.message) } } + + createTourGuideAccount = async (req, res, next) => { + try { + const { + email, + password, + lastname, + firstname, + gender, + dob, + phone_number + } = req.body + + const access_token = req.headers['authorization'] + const checkAdmin = await isAdmin(access_token) + if (!checkAdmin) throw new BadRequestError("Can't create tour guide account!") + + const tourGuide = await User.findOne({ + where: { email } + }) + if (tourGuide) throw new BadRequestError("Email is existed!") + const newTourGuide = await User.create({ + email, + password: await bcrypt.hash(password, 10), + lastname, + firstname, + gender, + dob, + phone_number, + role_user: RoleUser.GUIDER + }) + + if (!newTourGuide) throw new BadRequestError("Create new tour guide failed!") + return res.status(201).json({ + message: "Create tour guide successfully!", + tour_guide: newTourGuide + }) + + } catch (error) { + return res.status(500).json({ message: error.message }) + } + } } module.exports = new TourGuideController() \ No newline at end of file diff --git a/server/src/middlewares/authenticate.js b/server/src/middlewares/authenticate.js index c215bcd..738128f 100644 --- a/server/src/middlewares/authenticate.js +++ b/server/src/middlewares/authenticate.js @@ -1,6 +1,8 @@ 'use strict' const jwt = require('jsonwebtoken') +const { RoleUser } = require('../common/status') +const { AuthFailureError } = require('../core/error.response') const HEADER = { AUTHORIZATION: 'authorization' @@ -20,13 +22,31 @@ const authenticate = async (req, res, next) => { } } +const authenticateAdmin = async (req, res, next) => { + try { + const token = req.headers[HEADER.AUTHORIZATION] + if (!token || token === null || token === 'undefined') + return res.status(400).json({ status: 'Unauthorized', message: "You don't have access"}) + + const decodeUser = jwt.decode(token) + if (decodeUser['role_user'] != RoleUser.ADMIN ) { + throw new AuthFailureError("Invalid request!") + } + req.user = decodeUser + return next() + } catch (error) { + return res.status(500).json({ status: 'Fail', message: error.message }) + } +} + const isAdmin = async (token) => { const decodeUser = jwt.decode(token) const role_user = decodeUser['role_user'] - if (role === role_user) return true; + if (RoleUser.ADMIN === role_user) return true; } module.exports = { authenticate, + authenticateAdmin, isAdmin } \ No newline at end of file diff --git a/server/src/models/schedule.model.js b/server/src/models/schedule.model.js index 235d3f9..8fd83aa 100644 --- a/server/src/models/schedule.model.js +++ b/server/src/models/schedule.model.js @@ -17,6 +17,4 @@ Schedule.init({ } }, { sequelize, modelName: "schedule"} ) -// Schedule.belongsTo(Tour, { foreignKey: "tour_id" }) - module.exports = Schedule \ No newline at end of file diff --git a/server/src/postman/BKTravel.json b/server/src/postman/BKTravel.json index 2fb2a57..4dee468 100644 --- a/server/src/postman/BKTravel.json +++ b/server/src/postman/BKTravel.json @@ -9,106 +9,6 @@ { "name": "User", "item": [ - { - "name": "Get Wishlist by user", - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJlbWFpbCI6Imh1eS5uZ3V5ZW4yODAxMjAwMkBoY211dC5lZHUudm4iLCJyb2xlX3VzZXIiOiJjdXN0b21lciIsImlhdCI6MTcwNjA3NDI0NiwiZXhwIjoxNzA2MDc2MDQ2fQ.e8ceK8R1EA9l2Rg0L5EP9foKw1mja0OJuIFNqj8TiRM" - } - ], - "url": { - "raw": "http://localhost:8080/api/v1/users/2/wishlist", - "protocol": "http", - "host": [ - "localhost" - ], - "port": "8080", - "path": [ - "api", - "v1", - "users", - "2", - "wishlist" - ] - } - }, - "response": [] - }, - { - "name": "Add tour to wishlist", - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJlbWFpbCI6Imh1eTI4MDExQGdtYWlsLmNvbSIsInJvbGVfdXNlciI6ImN1c3RvbWVyIiwiaWF0IjoxNzE1NjA4Mjk2LCJleHAiOjE3MTU2MTAwOTZ9.yWxUVFMZqMSUQuqiKKFqXXzQePmi79wyG0zfhxCHRZ4" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"user_id\": 2,\r\n \"tour_id\": 1\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "http://localhost:8080/api/v1/users/wishlist", - "protocol": "http", - "host": [ - "localhost" - ], - "port": "8080", - "path": [ - "api", - "v1", - "users", - "wishlist" - ] - } - }, - "response": [] - }, - { - "name": "Add tour to cart", - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJlbWFpbCI6Imh1eS5uZ3V5ZW4yODAxMjAwMkBoY211dC5lZHUudm4iLCJyb2xlX3VzZXIiOiJjdXN0b21lciIsImlhdCI6MTcwNTg1OTEwMSwiZXhwIjoxNzA1ODYwOTAxfQ.CVQhYHm4g_-xFLV-rIezkRoyzOPogEkxm5nzrX6S930" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"user_id\": \"1\",\r\n \"tour\": {\r\n \"tour_id\": 2,\r\n \"adult_quantity\": 1,\r\n \"child_quantity\": 2\r\n }\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "http://localhost:8080/api/v1/users/carts", - "protocol": "http", - "host": [ - "localhost" - ], - "port": "8080", - "path": [ - "api", - "v1", - "users", - "carts" - ] - } - }, - "response": [] - }, { "name": "Register", "request": { @@ -569,6 +469,106 @@ } }, "response": [] + }, + { + "name": "Get Wishlist by user", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJlbWFpbCI6Imh1eS5uZ3V5ZW4yODAxMjAwMkBoY211dC5lZHUudm4iLCJyb2xlX3VzZXIiOiJjdXN0b21lciIsImlhdCI6MTcwNjA3NDI0NiwiZXhwIjoxNzA2MDc2MDQ2fQ.e8ceK8R1EA9l2Rg0L5EP9foKw1mja0OJuIFNqj8TiRM" + } + ], + "url": { + "raw": "http://localhost:8080/api/v1/users/2/wishlist", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "api", + "v1", + "users", + "2", + "wishlist" + ] + } + }, + "response": [] + }, + { + "name": "Add tour to wishlist", + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJlbWFpbCI6Imh1eTI4MDExQGdtYWlsLmNvbSIsInJvbGVfdXNlciI6ImN1c3RvbWVyIiwiaWF0IjoxNzE1NjA4Mjk2LCJleHAiOjE3MTU2MTAwOTZ9.yWxUVFMZqMSUQuqiKKFqXXzQePmi79wyG0zfhxCHRZ4" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"user_id\": 2,\r\n \"tour_id\": 1\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:8080/api/v1/users/wishlist", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "api", + "v1", + "users", + "wishlist" + ] + } + }, + "response": [] + }, + { + "name": "Add tour to cart", + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJlbWFpbCI6Imh1eS5uZ3V5ZW4yODAxMjAwMkBoY211dC5lZHUudm4iLCJyb2xlX3VzZXIiOiJjdXN0b21lciIsImlhdCI6MTcwNTg1OTEwMSwiZXhwIjoxNzA1ODYwOTAxfQ.CVQhYHm4g_-xFLV-rIezkRoyzOPogEkxm5nzrX6S930" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"user_id\": \"1\",\r\n \"tour\": {\r\n \"tour_id\": 2,\r\n \"adult_quantity\": 1,\r\n \"child_quantity\": 2\r\n }\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:8080/api/v1/users/carts", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "api", + "v1", + "users", + "carts" + ] + } + }, + "response": [] } ] }, @@ -2934,6 +2934,95 @@ } ] }, + { + "name": "Admin", + "item": [ + { + "name": "Create tour guide account", + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjozLCJlbWFpbCI6Imh1eTI4MDExMUBnbWFpbC5jb20iLCJyb2xlX3VzZXIiOiJhZG1pbiIsImlhdCI6MTcxNjIyMTQ3OCwiZXhwIjoxNzE2MjIzMjc4fQ.bzmuAFFQ32UTv3HPZw3AZLuLD-7sttDLlguuQxOEAVI" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"email\": \"tourguide1@gmail.com\",\r\n \"password\": \"123456\",\r\n \"gender\": \"male\",\r\n \"phone_number\": \"0979957328\",\r\n \"lastname\": \"Nguyen\",\r\n \"firstname\": \"Huy\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:8080/admin/management", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "admin", + "management" + ] + } + }, + "response": [] + }, + { + "name": "Get all booked numbers", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjozLCJlbWFpbCI6Imh1eTI4MDExMUBnbWFpbC5jb20iLCJyb2xlX3VzZXIiOiJhZG1pbiIsImlhdCI6MTcxNjIyMTQ3OCwiZXhwIjoxNzE2MjIzMjc4fQ.bzmuAFFQ32UTv3HPZw3AZLuLD-7sttDLlguuQxOEAVI" + } + ], + "url": { + "raw": "http://localhost:8080/admin/total-bookednumber", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "admin", + "total-bookednumber" + ] + } + }, + "response": [] + }, + { + "name": "Get total revenue", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjozLCJlbWFpbCI6Imh1eTI4MDExMUBnbWFpbC5jb20iLCJyb2xlX3VzZXIiOiJhZG1pbiIsImlhdCI6MTcxNjIyMTQ3OCwiZXhwIjoxNzE2MjIzMjc4fQ.bzmuAFFQ32UTv3HPZw3AZLuLD-7sttDLlguuQxOEAVI" + } + ], + "url": { + "raw": "http://localhost:8080/admin/total-revenue", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "admin", + "total-revenue" + ] + } + }, + "response": [] + } + ] + }, { "name": "Remove tour to wishlist", "request": { @@ -3131,7 +3220,7 @@ { "name": "Get all tour guides", "request": { - "method": "POST", + "method": "GET", "header": [ { "key": "Authorization", diff --git a/server/src/routes/admin/index.js b/server/src/routes/admin/index.js new file mode 100644 index 0000000..ee4b8aa --- /dev/null +++ b/server/src/routes/admin/index.js @@ -0,0 +1,14 @@ +'use strict' + +const express = require("express") +const router = express.Router() +const { asyncHandler } = require('../../auth/checkAuth') +const tourGuideController = require("../../controllers/tour_guide.controller") +const adminController = require("../../controllers/admin.controller") +const { authenticateAdmin } = require("../../middlewares/authenticate") + +router.post("/manage-account", authenticateAdmin, asyncHandler(tourGuideController.createTourGuideAccount)) +router.get("/total-bookednumber", authenticateAdmin, asyncHandler(adminController.getCustomerNumber)) +router.get("/total-revenue", authenticateAdmin, asyncHandler(adminController.getTotalRevenue)) + +module.exports = router \ No newline at end of file diff --git a/server/src/routes/index.js b/server/src/routes/index.js index dd6c693..820c169 100644 --- a/server/src/routes/index.js +++ b/server/src/routes/index.js @@ -5,6 +5,7 @@ const router = express.Router() const { pushToLogDiscord } = require("../middlewares/index") router.use(pushToLogDiscord) +router.use('/admin', require("./admin")) router.use('/api/v1/auth', require("./auth")) router.use('/api/v1/attractions', require("./attraction")) router.use('/api/v1/destinations', require("./destination"))