+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 | + +3x + + + +1x + + + +1x + + + + + + + +1x +1x + +1x + + + + + + + + +1x + + + + + + +1x + + +1x + + + + + + + + +1x + + + +1x + + + + + +1x + + + + + + + +1x + + + + + + + +3x | 'use strict' + +const {category} = require('../models/index.js'); + +class CategoryController{ + static toList(req, res, next){ + category.findAll({ + order: ['name'], + }) + .then(result => { + res.status(200).json(result) + }) + .catch(err => { + next(err) + }) + } + + static addData(req, res, next){ + console.log("ADDDATA") + category.create(req.body) + .then(result => { + res.status(201).json(result) + }) + .catch(err => { + console.log(err) + next(err) + }) + } + + static updateData(req, res, next){ + category.update(req.body, { + where: { + id: req.params.id + }, + returning: true + }) + .then(result => { + Iif (result[0] === 0){ + res.status(404).json("Data Not Found") + } else { + res.status(200).json(result[1][0]) + } + }) + .catch(err => { + next(err) + }) + } + + static deleteData(req, res, next){ + category.findOne({ + where: {id: req.params.id} + }) + .then(result => { + Iif (!result) { + throw ({ + name: "NotFound", + message: `category with Id ${req.params.id} Not Found` + }) + } else { + return category.destroy({ + where: { + id: req.params.id + } + }) + } + }) + .then(() => { + res.status(200).json({"message": "category success to delete"}) + }) + .catch(err => { + next(err) + }) + } +} + +module.exports = CategoryController; |
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 | + +3x + + + +1x + + + + +1x + + + + + + + +1x + +1x + + + + + + + +1x + + + + + + +1x + + +1x + + + + + + + + +1x + + + +1x + + + + + +1x + + + + + + + +1x + + + + + + + +3x | 'use strict' + +const {product, category} = require('../models/index.js'); + +class ProductController{ + static toList(req, res, next){ + product.findAll({ + include: [category], + order: ['name'], + }) + .then(result => { + res.status(200).json(result) + }) + .catch(err => { + next(err) + }) + } + + static addData(req, res, next){ + product.create(req.body) + .then(result => { + res.status(201).json(result) + }) + .catch(err => { + next(err) + }) + } + + static updateData(req, res, next){ + product.update(req.body, { + where: { + id: req.params.id + }, + returning: true + }) + .then(result => { + Iif (result[0] === 0){ + res.status(404).json("Data Not Found") + } else { + res.status(200).json(result[1][0]) + } + }) + .catch(err => { + next(err) + }) + } + + static deleteData(req, res, next){ + product.findOne({ + where: {id: req.params.id} + }) + .then(result => { + Iif (!result) { + throw ({ + name: "NotFound", + message: `product with Id ${req.params.id} Not Found` + }) + } else { + return product.destroy({ + where: { + id: req.params.id + } + }) + } + }) + .then(() => { + res.status(200).json({"message": "product success to delete"}) + }) + .catch(err => { + next(err) + }) + } +} + +module.exports = ProductController; |
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 | 3x +3x +3x + + + +2x + + + + + +1x + + + + +1x + + + + +1x + + + + +2x + + + +2x +1x + + + + + +1x + +1x + + + + + + + +1x + + + + +1x + + + + +1x + + + + +3x | const {user} = require("../models") +const { generateToken } = require('../helpers/jwt.js') +const { comparePassword } = require('../helpers/bcrypt') + +class UsersController{ + static register(req, res, next) { + user.create({ + email: req.body.email, + password: req.body.password, + role: req.body.role + }) + .then(result => { + const token = generateToken({ + id: result.id, + email: result.email, + }); + + res.status(201).json({ + access_token: token + }) + }) + .catch(err => { + next(err) + }) + } + + static login(req, res, next){ + user.findOne({ + where: {email: req.body.email} + }) + .then(result => { + if (!result) { + throw{ + name: "LoginError", + message: `User Or Password Incorrect"` + } + } + + const checkPW = comparePassword(req.body.password, result.password) + + Iif (!checkPW){ + throw { + name: "LoginError", + message: "User Or Password Incorrect" + } + } + + //kirim token + const token = generateToken({ + id: result.id, + email: result.email, + }); + + res.status(200).json({ + access_token: token, + }) + }) + .catch(err => { + next(err) + }) + } +} + +module.exports = UsersController |
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+File | ++ | Statements | ++ | Branches | ++ | Functions | ++ | Lines | ++ |
---|---|---|---|---|---|---|---|---|---|
CategoryController.js | +
+
+ |
+ 66.67% | +14/21 | +50% | +2/4 | +69.23% | +9/13 | +66.67% | +14/21 | +
ProductController.js | +
+
+ |
+ 68.42% | +13/19 | +50% | +2/4 | +69.23% | +9/13 | +68.42% | +13/19 | +
UserController.js | +
+
+ |
+ 94.12% | +16/17 | +75% | +3/4 | +100% | +6/6 | +94.12% | +16/17 | +
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 | 3x + +3x +3x +3x +3x + + +3x +1x +1x + + +3x + + | const bcrypt = require("bcryptjs") + +const hashPassword = (userPassword) => { + const salt = bcrypt.genSaltSync(10); + const hash = bcrypt.hashSync(userPassword, salt); + return hash; +} + +const comparePassword = (userPassword, hashPassword) => { + const isCorrect = bcrypt.compareSync(userPassword, hashPassword) + return isCorrect +} + +module.exports = { + hashPassword, comparePassword, +} |
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
++ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 | 3x +3x + +3x +4x +4x + +4x + + + + + +3x + +16x +8x + + +3x + + | const jwt = require('jsonwebtoken');
+const SECRET_KEY = process.env.SECRET_KEY_JWT;
+
+const generateToken = (payload) => {
+ try{
+ const token = jwt.sign(payload, SECRET_KEY);
+ // console.log(token)
+ return token;
+ } catch ( err ) {
+ console.log(err)
+ }
+}
+
+const verifyToken = (token) => {
+ // console.log("verify", token)
+ const decoded = jwt.verify(token, SECRET_KEY)
+ return decoded;
+}
+
+module.exports = {
+ generateToken, verifyToken,
+} |
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+File | ++ | Statements | ++ | Branches | ++ | Functions | ++ | Lines | ++ |
---|---|---|---|---|---|---|---|---|---|
index.js | +
+
+ |
+ 100% | +13/13 | +50% | +1/2 | +100% | +0/0 | +100% | +12/12 | +
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 | 3x + +3x +3x +3x +3x +3x + +3x +3x +3x + +3x +3x + +3x | Eif(process.env.NODE_ENV != "production") require("dotenv").config();
+
+const express = require('express');
+const errHandler = require('./middlewares/errHandler.js');
+const cors = require('cors')
+const app = express();
+const routes = require('./routes');
+
+app.use(cors());
+app.use(express.urlencoded({extended:true}));
+app.use(express.json());
+
+app.use('/', routes)
+app.use(errHandler);
+
+module.exports = app |
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 | 3x +3x +3x + + +16x +16x +16x +8x +8x + + + +8x + + + + + + +8x + + + + + +8x + + + + + +8x + + + +3x +6x + +6x +6x + + + + + + + + +3x + + | const { verifyToken } = require('../helpers/jwt'); +const {user} = require('../models') +const {product} = require('../models') + +function authentication(req, res, next){ + try{ + const {access_token} = req.headers; + const dataDecoded = verifyToken(access_token); + console.log("AUTH", dataDecoded) + user.findOne({ + where: {id: dataDecoded.id} + }) + .then(result =>{ + Iif(!result) { + throw{ + name: "AuthenticationError", + message: `user with id: ${dataDecoded.id} not found`, + } + } + + req.currentUser = { + id: result.id, + email: result.email, + role: result.role + } + + next(); + }) + .catch(err => { + next("authentication : " + err) + }) + } catch (error) { + next("authentication : " + error) + } +} + +const authorizationRole = (req, res, next) => { + const id = req.currentUser.id + + Eif (req.currentUser.role == "admin"){ + return next(); + } else { + throw{ + name: "AuthorizationError", + message: "Role of User Must Admin" + } + } +} + +module.exports= { + authentication, authorizationRole +} |
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 | + + + +10x + +1x +1x +1x + +1x +1x +1x + + + + + + + +8x +8x + + + + +8x +8x + + +10x + +10x + + + + +3x | function errHandler(err, req, res, next){ + let statusCode; + let message; + + switch (err.name){ + case "LoginError": + statusCode = 400; + message = "Email or Password is incorrect" + break; + case "SequelizeValidationError": + statusCode = 400; + message = err.errors[0].message + break; + case "NotFound": + statusCode = 404; + message = err.message + case "AuthorizationError": + statusCode = 401; + message = err.message + default: + Eif (err.message == undefined) { + message = err + } else { + message = err.message; + } + + statusCode = 500; + break; + } + + console.log("DARI ERROR HANDLE : " , err) + + res.status(statusCode).json({ + message: message + }) +} + +module.exports = errHandler; |
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+File | ++ | Statements | ++ | Branches | ++ | Functions | ++ | Lines | ++ |
---|---|---|---|---|---|---|---|---|---|
auth.js | +
+
+ |
+ 85% | +17/20 | +50% | +2/4 | +75% | +3/4 | +85% | +17/20 | +
errHandler.js | +
+
+ |
+ 73.68% | +14/19 | +57.14% | +4/7 | +100% | +1/1 | +73.68% | +14/19 | +
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 | + + +3x +3x + + + + + + + +3x + + +3x + + + + + +3x + | 'use strict'; +const { + Model +} = require('sequelize'); +module.exports = (sequelize, DataTypes) => { + class category extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + category.hasMany(models.product, {foreignKey: "categoryid"}) + } + }; + category.init({ + name: DataTypes.STRING + }, { + sequelize, + modelName: 'category', + }); + return category; +}; |
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+File | ++ | Statements | ++ | Branches | ++ | Functions | ++ | Lines | ++ |
---|---|---|---|---|---|---|---|---|---|
category.js | +
+
+ |
+ 100% | +5/5 | +100% | +0/0 | +100% | +2/2 | +100% | +5/5 | +
index.js | +
+
+ |
+ 95% | +19/20 | +66.67% | +6/9 | +100% | +3/3 | +95% | +19/20 | +
product.js | +
+
+ |
+ 100% | +5/5 | +100% | +0/0 | +100% | +2/2 | +100% | +5/5 | +
user.js | +
+
+ |
+ 100% | +7/7 | +100% | +0/0 | +100% | +3/3 | +100% | +7/7 | +
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 | + +3x +3x +3x +3x +3x +3x +3x + + +3x + + +3x + + +3x + + +12x + + +9x +9x + + +3x +9x +9x + + + +3x +3x + +3x + | 'use strict'; + +const fs = require('fs'); +const path = require('path'); +const Sequelize = require('sequelize'); +const basename = path.basename(__filename); +const env = process.env.NODE_ENV || 'development'; +const config = require(__dirname + '/../config/config.json')[env]; +const db = {}; + +let sequelize; +Iif (config.use_env_variable) { + sequelize = new Sequelize(process.env[config.use_env_variable], config); +} else { + sequelize = new Sequelize(config.database, config.username, config.password, config); +} + +fs + .readdirSync(__dirname) + .filter(file => { + return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js'); + }) + .forEach(file => { + const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes); + db[model.name] = model; + }); + +Object.keys(db).forEach(modelName => { + Eif (db[modelName].associate) { + db[modelName].associate(db); + } +}); + +db.sequelize = sequelize; +db.Sequelize = Sequelize; + +module.exports = db; + |
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 | + + +3x +3x + + + + + + + + +3x + + +3x + + + + + + + + + +3x + | 'use strict'; +const { + Model +} = require('sequelize'); +module.exports = (sequelize, DataTypes) => { + class product extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + product.belongsTo(models.category, {foreignKey: "categoryid"}) + } + }; + product.init({ + name: DataTypes.STRING, + image_url: DataTypes.STRING, + price: DataTypes.INTEGER, + stock: DataTypes.INTEGER, + categoryid: DataTypes.INTEGER + }, { + sequelize, + modelName: 'product', + }); + return product; +}; |
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 | + + +3x +3x +3x + + + + + + + + + + +3x + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1x +1x + + + +3x + | 'use strict'; +const { + Model +} = require('sequelize'); +const {hashPassword} = require("../helpers/bcrypt"); +module.exports = (sequelize, DataTypes) => { + class user extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + } + }; + user.init({ + email: { + type: DataTypes.STRING, + allowNull: false, + unique: { + msg: "Email has been used" + }, + validate: { + notEmpty: true + } + }, + password: { + type: DataTypes.STRING, + allowNull: false, + validate: { + notEmpty: true, + } + }, + role: { + type: DataTypes.STRING, + allowNull: false, + validate: { + notEmpty: true + }, + notNull: { + msg: "Role Can`t be Null" + } + } + }, { + sequelize, + modelName: 'user', + hooks: { + beforeCreate: (u, opt) => { + const hashedPassword = hashPassword(u.password); + u.password = hashedPassword; + } + } + }); + return user; +}; |
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 | 3x +3x +3x +3x + +3x +3x +3x +3x + +3x | const express = require('express'); +const CategoryController = require('../controllers/CategoryController'); +const router = express.Router(); +const {authorizationRole} = require('../middlewares/auth.js') + +router.get('/', CategoryController.toList) +router.post('/', authorizationRole, CategoryController.addData) +router.put('/:id', authorizationRole, CategoryController.updateData) +router.delete('/:id', authorizationRole, CategoryController.deleteData) + +module.exports = router; |
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+File | ++ | Statements | ++ | Branches | ++ | Functions | ++ | Lines | ++ |
---|---|---|---|---|---|---|---|---|---|
categories.js | +
+
+ |
+ 100% | +9/9 | +100% | +0/0 | +100% | +0/0 | +100% | +9/9 | +
index.js | +
+
+ |
+ 100% | +7/7 | +100% | +0/0 | +100% | +0/0 | +100% | +7/7 | +
products.js | +
+
+ |
+ 100% | +9/9 | +100% | +0/0 | +100% | +0/0 | +100% | +9/9 | +
users.js | +
+
+ |
+ 100% | +6/6 | +100% | +0/0 | +100% | +0/0 | +100% | +6/6 | +
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+1 +2 +3 +4 +5 +6 +7 +8 +9 +10 | 3x +3x + +3x +3x +3x +3x + +3x + | const router = require('express').Router() +const {authentication} = require('../middlewares/auth.js') + +router.use('/users', require('./users.js')) +router.use(authentication) +router.use('/categories', require('./categories')) +router.use('/products', require('./products')) + +module.exports = router + |
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 | 3x +3x +3x +3x + +3x +3x +3x +3x + +3x | const express = require('express'); +const ProductController = require('../controllers/ProductController.js'); +const router = express.Router(); +const {authorizationRole} = require('../middlewares/auth.js') + +router.get('/', ProductController.toList) +router.post('/', authorizationRole, ProductController.addData) +router.put('/:id', authorizationRole, ProductController.updateData) +router.delete('/:id', authorizationRole, ProductController.deleteData) + +module.exports = router; |
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+1 +2 +3 +4 +5 +6 +7 | 3x +3x +3x + +3x +3x +3x | const express = require('express'); +const UsersController = require('../controllers/UserController'); +const router = express.Router(); + +router.post('/register', UsersController.register) +router.post('/login', UsersController.login) +module.exports = router; |
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+File | ++ | Statements | ++ | Branches | ++ | Functions | ++ | Lines | ++ |
---|---|---|---|---|---|---|---|---|---|
e-commerce-server | +
+
+ |
+ 100% | +13/13 | +50% | +1/2 | +100% | +0/0 | +100% | +12/12 | +
e-commerce-server/controllers | +
+
+ |
+ 75.44% | +43/57 | +58.33% | +7/12 | +75% | +24/32 | +75.44% | +43/57 | +
e-commerce-server/helpers | +
+
+ |
+ 95% | +19/20 | +100% | +0/0 | +100% | +4/4 | +95% | +19/20 | +
e-commerce-server/middlewares | +
+
+ |
+ 79.49% | +31/39 | +54.55% | +6/11 | +80% | +4/5 | +79.49% | +31/39 | +
e-commerce-server/models | +
+
+ |
+ 97.3% | +36/37 | +66.67% | +6/9 | +100% | +10/10 | +97.3% | +36/37 | +
e-commerce-server/routes | +
+
+ |
+ 100% | +31/31 | +100% | +0/0 | +100% | +0/0 | +100% | +31/31 | +