I am trying to call registerValidation function that is defined in file validation.js from auth.js, but error appears that
UnhandledPromiseRejectionWarning: Error: Invalid message options
Can anyone tell me why and how to correct it?
auth.js
const router = require("express").Router();
const User = require("../model/User")
const {registerValidation} = require("./validation")
router.post('/register', async(req, res)=>{
//Lets validate the data
//error appears here
const {error} = registerValidation(req.body);
if(error){
return res.status(400).send(error.details[0].message)
}
const user = new User({
name:req.body.name,
email:req.body.email,
password:req.body.password
});
try{
const savedUser = await user.save();
res.send(savedUser);
}catch(err){
res.status(400).send(err)
}
})
module.exports = router;
validation.js
//VALIDATION
const Joi = require("#hapi/joi")
const registerValidation = (data) => {
const schema = Joi.object({
name:Joi.string().min(6).required(),
email:Joi.string().min(6).required().email(),
password:Joi.string().min(6).required()
});
return schema.validate(data, schema)
}
const loginValidation = data =>{
const schema = Joi.object({
email:Joi.string().min(6).required().email(),
password:Joi.string().min(6).required()
});
return schema.validate(data, schema)
}
module.exports = {registerValidation, loginValidation};
You need to wrap your functions inside an object and then export that object, like in the following example:
const registerValidation = (data) => {...}
const loginValidation = (data) => {...}
module.exports = {
registerValidation,
loginValidation
}
Alternatively, since module.exports is an object itself, you could do something like the following:
const registerValidation = (data) => {...}
const loginValidation = (data) => {...}
module.exports.registerValidation = registerValidation;
module.exports.loginValidation = loginValidation;
the registerValidation and loginValidation function should be like given below
const Joi = require("#hapi/joi");
const registerValidation = (data) => {
console.log("body ", data)
const schema = Joi.object({
name:Joi.string().min(6).required(),
email:Joi.string().min(6).required().email(),
password:Joi.string().min(6).required()
});
return schema.validate(data) //change here
}
const loginValidation = data =>{
const schema = Joi.object({
email:Joi.string().min(6).required().email(),
password:Joi.string().min(6).required()
});
return schema.validate(data) //change here
}
module.exports = {registerValidation, loginValidation};
Related
I am trying to use sharp in my MERN application, I sent a request from my frontend and it is undefined in my sharp middleware but if I get rid of the sharp middleware the req is defined later on. If I log the request in createCountry, the body is defined, if I log it in convertToWebP, it is not.
the route is the one that says "/new" below:
const express = require("express");
const router = express.Router();
const { storage } = require("../imageupload/cloudinary.js");
const multer = require("multer");
const {
getCountry,
createCountry,
getCountries,
updateCountry,
deleteCountry,
getAllCountries,
} = require("../controllers/country.js");
const {convertToWebP} = require('../middlewares/toWebP')
const { isLoggedIn, authorizeCountry, validateCountry } = require("../middlewares/auth");
const catchAsync = require("../utils/catchAsync");
const ExpressError = require("../utils/ExpressError");
const upload = multer({ storage: storage });
router.get("/", getCountries);
router.get('/getAll', getAllCountries);
router.post("/new", isLoggedIn, converToWebP, upload.array("images"), createCountry);
router.get("/:countryId", getCountry);
router.patch("/:countryId", validateCountry, authorizeCountry, upload.array("images", 8), updateCountry);
router.delete("/:countryId", authorizeCountry, deleteCountry);
module.exports = router;
the code for create country is here:
exports.createCountry = async (req, res) => {
const { name, description, tags, location, cjLink } = req.body;
const creator = req.user._id;
const images = req.files.map((file) => {
return { image: file.path, publicId: file.filename };
});
try {
const geoData = await geocoder
.forwardGeocode({
query: req.body.location,
limit: 1,
})
.send();
const geometry = geoData.body.features[0].geometry;
const country = new Country({
name,
description,
tags,
creator,
location, //: //geometry
geometry,
url: '',
cjLink: cjLink,
});
const overall = new Overall({
name,
description,
tags,
creator,
location, //: //geometry
geometry,
url: '',
cjLink: cjLink,
});
country.images.push(...images);
country.headerImage.push(...images);
const data = await country.save();
overall.url = `/country/${data._id}`
data.url = `/country/${data._id}`
overall.save();
data.save();
return res.status(201).json(data);
} catch (error) {
return console.log("error during create country", error);
}
};
And lastly the code for the convertToWebP is here:
const sharp = require("sharp");
const { cloudinary } = require("../imageupload/cloudinary");
exports.convertToWebP = async (req, res, next) => {
try {
req.files = await Promise.all(req.files.map(async (file) => {
const buffer = await sharp(file.buffer)
.toFormat('webp')
.toBuffer();
return { ...file, buffer, originalname: `${file.originalname}.webp` };
}));
next();
} catch (error) {
res.status(500).json({ message: error.message });
}
};
Any help is appreciated! I tried console.log as described above, I tried to change the order of the middleware and that does not work either, and I tried logging the req.body directly from the route and it came up as an empty object
You cannot acces req.files before you use multer middleware
You have to reorder
router.post("/new", isLoggedIn, upload.array("images"), converToWebP, createCountry);
In my application I get the following errors when I'm trying to reach GET, PUT, DELETE routes (tried POSTMAN and VSCode REST Server):
Error 1:
GET by ID : `Incorrect Syntax near '83'.`
Error 2:
GET ALL : `Incorrect Syntax near '83'.`
Error 3:
PUT : `Incorrect syntax near '85'.`
Error 4:
DELETE : `Incorrect syntax near '68'.`
I have googled the error but most of them are related to spacing errors in parameters in the SQL query but I have checked mine and the queries I have are all correct compared to those.
I suspect if this related to any SQL Server related encoding but not sure.
Below are some of my coding as a start to investigate:
eventController.js
'use strict';
const eventData = require('../data/events');
const getEvents = async (req, res, next) => {
try {
const events = await eventData.getEvents();
res.send(events);
}catch (error) {
res.status(400).send(error.message);
}
}
const getEvent = async (req, res, next) => {
try {
const eventId = req.params.id;
const oneEvent = await eventData.getById(eventId);
res.send(oneEvent)
} catch (error) {
res.status(400).send(error.message)
}
}
const updateEvent = async (req, res, next) => {
try {
const eventId = req.params.id;
const data = req.body;
const updated = await eventData.updateEvent(eventId, data);
res.send(updated);
} catch (error) {
res.status(400).send(error.message)
}
}
const deleteEvent = async (req, res, next) => {
try {
const eventId = req.params.id;
const deletedevent = await eventData.deleteEvent(eventId);
res.send(deletedevent);
} catch (error) {
res.status(400).send(error.message)
}
}
module.exports = {
getEvents,
getEvent,
updateEvent,
deleteEvent
}
eventslist.sql
SELECT [ord_type],
[ord_no],
[line_seq_no],
[lvl_no],
[cmt_type],
[cmt_seq_no],
[cmt],
[CMT_DOC_TYPE],
[EXTRA_1],
[extra_2],
[extra_3],
[extra_4],
[extra_5],
[extra_6],
[extra_7],
[extra_8],
[extra_9],
[extra_10],
[extra_11],
[extra_12],
[extra_13],
[extra_14],
[extra_15],
[FILLER_0001],
[ID],
[is_ext],
[RowVersion]
FROM [100].[dbo].[OELINCMT_SQL]
utils.js
'use strict';
const fs = require('fs-extra');
const {join} = require('path');
const loadSqlQueries = async (folderName) => {
const filePath = join(process.cwd(), 'data', folderName);
const files = await fs.readdir(filePath);
const sqlFiles = await files.filter(f => f.endsWith('.sql'));
const queries = {};
for (const sqlFile of sqlFiles) {
const query = await fs.readFileSync(join(filePath, sqlFile));
queries[sqlFile.replace(".sql", "")] = query
}
return queries;
}
module.exports = {
loadSqlQueries
}
UPDATE : Added data/events
index.js
'use strict';
const utils = require('../utils');
const config = require('../../config');
const sql = require('mssql');
const getEvents = async () => {
try {
let pool = await sql.connect(config.sql);
const sqlQueries = await utils.loadSqlQueries('events');
const list = await pool.request().query(sqlQueries.eventslist);
return list.recordset;
} catch (error) {
return error.message;
}
}
const getById = async (eventId) => {
try {
let pool = await sql.connect(config.sql);
const sqlQueries = await utils.loadSqlQueries('events');
const oneEvent = await pool.request()
.input('eventId', sql.Char(8), eventId)
.query(sqlQueries.eventbyId);
return oneEvent.recordset;
} catch (error) {
return error.message;
}
}
const updateEvent = async (eventId, eventData) => {
try {
let pool = await sql.connect(config.sql);
const sqlQueries = await utils.loadSqlQueries('events');
const update = await pool.request()
.input('eventId', sql.Char(8), eventId)
.input('cmt', sql.NVarChar(4000), eventData.cmt)
.query(sqlQueries.updateEvent);
return update.recordset;
} catch (error) {
return error.message
}
}
const deleteEvent = async (eventId) => {
try {
let pool = await sql.connect(config.sql);
const sqlQueries = await utils.loadSqlQueries('events');
const deleted = await pool.request()
.input('eventId', sql.Char(8), eventId)
.query(sqlQueries.deleteEvent);
return deleted.recordset;
} catch (error) {
return error.message
}
}
module.exports = {
getEvents,
getById,
updateEvent,
deleteEvent
}
eventbyId.sql
SELECT [ord_type]
,[ord_no]
,[line_seq_no]
,[lvl_no]
,[cmt_type]
,[cmt_seq_no]
,[cmt]
,[CMT_DOC_TYPE]
,[EXTRA_1]
,[extra_2]
,[extra_3]
,[extra_4]
,[extra_5]
,[extra_6]
,[extra_7]
,[extra_8]
,[extra_9]
,[extra_10]
,[extra_11]
,[extra_12]
,[extra_13]
,[extra_14]
,[extra_15]
,[FILLER_0001]
,[ID]
,[is_ext]
,[RowVersion]
FROM [100].[dbo].[OELINCMT_SQL]
WHERE [ord_no] = #eventId
Request for GET ALL via POSTMAN
Request for GET by ID via POSTMAN
Request for GET ALL via REST Server
RAW Body of GET ALL request
RAW Body of GET by ID request
my code in github, but I didn't upload the latest version:
https://github.com/godzillalogan/markdownblog
I use node.js and express.js framework. Database use mongoDB.
I am using the package Imgur and dotenv, try to upload image to imgur.
But I encounter some bug:
bug:
App is running on http://localhost:3000
mongodb connected!
TypeError: Cannot read property 'then' of undefined
at Promise (D:\Github\markdownblog\helpers\file-helpers.js:26:7)
at new Promise (<anonymous>)
at imgurFileHandler (D:\Github\markdownblog\helpers\file-helpers.js:23:10)
at router.put (D:\Github\markdownblog\routes\modules\admin.js:115:26)
at process._tickCallback (internal/process/next_tick.js:68:7)
D:\Github\markdownblog\node_modules\imgur-node-api\lib\imgur.js:34
_cb(null, body);
^
TypeError: _cb is not a function
at Request._callback (D:\Github\markdownblog\node_modules\imgur-node-api\lib\imgur.js:34:9)
at Request.self.callback (D:\Github\markdownblog\node_modules\request\index.js:142:22)
at Request.emit (events.js:182:13)
at Request.<anonymous> (D:\Github\markdownblog\node_modules\request\index.js:856:14)
at Request.emit (events.js:187:15)
at IncomingMessage.<anonymous> (D:\Github\markdownblog\node_modules\request\index.js:808:12)
at IncomingMessage.emit (events.js:187:15)
at endReadableNT (_stream_readable.js:1094:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
[nodemon] app crashed - waiting for file changes before starting...
Here is my code:
app.js:
const path = require('path') // 引入 path 套件
const express = require('express')
const session = require('express-session')
const bodyParser = require('body-parser') //新版express以內建body-parser
const { engine } = require('express-handlebars');
const flash = require('connect-flash')
if (process.env.NODE_ENV !== 'production') { //要放在const routes = require('./routes')前面
require('dotenv').config()
}
const routes = require('./routes')
const app = express()
const PORT = process.env.PORT || 3000
const methodOverride = require('method-override') // 載入 method-override
//others code............
helpers/file-helpers.js:
const fs = require('fs') // 引入 fs 模組, fs 模組是 Node.js 提供專門來處理檔案的原生模組
//載入 imgur 套件
const imgur = require('imgur-node-api')
const IMGUR_CLIENT_ID = process.env.IMGUR_CLIENT_ID
console.log('IMGUR_CLIENT_ID:',IMGUR_CLIENT_ID)
imgur.setClientID(IMGUR_CLIENT_ID)
const localFileHandler = file => { // file 是 multer 處理完的檔案
return new Promise((resolve, reject) => {
if (!file) return resolve(null)
const fileName = `upload/${file.originalname}`
return fs.promises.readFile(file.path)
.then(data => fs.promises.writeFile(fileName, data))
.then(() => resolve(`/${fileName}`))
.catch(err => reject(err))
})
}
const imgurFileHandler = file => {
return new Promise((resolve, reject) => {
if (!file) return resolve(null)
return imgur.upload(file.path)
.then(img => {
// resolve(img?.link || null) // 檢查 img 是否存在
resolve(img ? img.link : null)
})
.catch(err => reject(err))
})
}
module.exports = {
localFileHandler,
imgurFileHandler //img
}
routes/modules/admin:
const express = require('express')
const router = express.Router()
const Article = require('../../models/article');
const Category = require('../../models/category');
const User = require('../../models/user');
const Contact = require('../../models/contact');
const upload = require('../../middleware/multer') // 載入 multer
const { imgurFileHandler } = require('../../helpers/file-helpers') // 將 file-helper 載進來
////others code....
//edit user
router.put('/users/:id', upload.single('avatar'), async (req, res)=>{
try{
console.log('有到edit user嗎')
const _id = req.params.id
const { name,avatar,introduction } = req.body
const { file } = req // 把檔案取出來
const user = await User.findOne({ _id})
const filePath = await imgurFileHandler(file) // 把檔案傳到 file-helper 處理
user.name = name
// user.cover = filePath || user.cover
user.avatar = filePath || user.avatar
user.introduction = introduction
await user.save()
res.redirect('/about')
}catch(e){
console.log(e)
res.redirect(`/admin/users`)
}
// const {title,description,markdown} = req.body //和new一樣才能將markdown轉成html
// Article.create({...req.body})
// res.redirect('/')
////others code....
})
What I have try:
I think it is about promise problem, and localFileHandler in helpers/file-helpers.js is work successful , but why imgurFileHandler in helpers/file-helpers.js is not work .
Thank you for your help.
It's probably because imgur.upload() dosent support promises and you should pass a callback as a second argument to the function like this :
imgur.upload(file.path, (err, response) => {
if(err) {
return null
}
return response.data.link
})
I move it from helpers/file-helpers.js to routes/modules/admin.js. And the way
is success.
But I think there would have another better way.
routes/modules/admin.js
I add Imgur to the route in create article,edit article and edit user.
routes/modules/admin.js
//Create
router.post('/articles', upload.single('image'), async (req,res)=>{
// console.log(req.body)
// const article = new Article({
// title: req.body.title,
// description: req.body.description,
// markdown: req.body.markdown
// });
try{
const {title,category,description,markdown} = req.body
const{file} = req
console.log('file:',file)
if (file){
imgur.setClientID(IMGUR_CLIENT_ID)
imgur.upload(file.path,(err, img) =>{
Article.create({...req.body, image: file ? img.data.link: null})
})
}else{
Article.create({...req.body})
}
res.redirect('/admin/articles')
} catch(e){
console.log(e)
res.render('admin/articles',{ article })
}
})
////Update
//到edit頁
router.get('/articles/edit/:id', async (req, res) => {
// const _id = req.params.id
// return Article.findOne({ _id})
// .lean()
// .then((article) => res.render('edit', { article}))
// .catch(error => console.log(error))
try{
const _id = req.params.id
const article = await Article.findOne({ _id}).lean()
const categories = await Category.find().lean().sort({createdAt:'desc'})
res.render('edit', { article,categories})
}catch{
console.log(e)
res.redirect(`/articles/edit/:id`)
}
})
//edit article
router.put('/articles/:id', upload.single('image'), async (req, res)=>{
try{
const _id = req.params.id
const { title,description,markdown,category } = req.body
const { file } = req // 把檔案取出來
const article = await Article.findOne({ _id})
if (file){
// const filePath = await imgurFileHandler(file) // 把檔案傳到 file-helper 處理
imgur.setClientID(IMGUR_CLIENT_ID)
imgur.upload(file.path,async (err, img) =>{
// Article.update({...req.body, image: file ? img.data.link: article.image})
article.title = title
article.description = description
article.markdown = markdown
article.category = category
article.image = img.data.link
await article.save()
})
}else{
article.title = title
article.description = description
article.markdown = markdown
article.category = category
await article.save()
}
res.redirect('/admin/articles')
}catch(e){
console.log(e)
res.redirect(`/admin/articles`)
}
// const {title,description,markdown} = req.body //和new一樣才能將markdown轉成html
// Article.create({...req.body})
// res.redirect('/')
})
I want to verify a jwt, and I get this back:
Promise {
{
id: 'eec46cd4-dfb8-4495-8a25-10b6232e4b3c',
iat: 1619072483,
exp: 1625120483
}
}
How can I only get the ID ?
.............
...........
Code
const jwt = require('jsonwebtoken');
const util = require('util');
const jwtVerifyAsync = util.promisify(jwt.verify);
module.exports = async (req, res) => {
const token = req.body.body;
try {
const verify = jwtVerifyAsync(token, 'SECRET-TOKEN');
console.log(verify)
} catch(e) {
console.log(e);
return e;
}
};
You should add await and then check the value:
const jwt = require('jsonwebtoken');
const util = require('util');
const jwtVerifyAsync = util.promisify(jwt.verify);
module.exports = async (req, res) => {
const token = req.body.body;
try {
const verify = await jwtVerifyAsync(token, 'SECRET-TOKEN'); // add await as it will return the promise
console.log(verify)
} catch(e) {
console.log(e);
return e;
}
};
I am working on a MERN SaaS application and I have read all manner of documents on multi-tenancy, where the goal is to create a layer of data isolation above the level of the user. putting all the info together I came about this solution which suggests making use of "continous-local-storage" However, after implementing it, I can't really get it to work, all I have seems logically right, I really can't figure out the issue. After implementation, my application refuses to load data from the database...
//lib/storage.js
const createNamespace = require('continuation-local-storage').createNamespace;
const namespaceName = ('request');
const ns = createNamespace(namespaceName);
const bindCurrentNamespace=function(req, res, next){
ns.bindEmitter(req);
ns.bindEmitter(res);
ns.run(() => {
next();
});
}
const setCurrentTenantId=function(tenantId){
return ns.set('tenantId', tenantId);
}
const getCurrentTenantId=function(){
return ns.get('tenantId');
}
module.exports ={
bindCurrentNamespace:function(){},
setCurrentTenantId:function(){},
getCurrentTenantId:function(){}
}
Sever.js
**********
// some code above
const storage= require('./lib/storage')
// multitenant logic
const BindCurrentNamespace = storage.bindCurrentNamespace
app.use(BindCurrentNamespace);
app.use((req, res, next) => {
// Get current user from session or token
const user = req.user
// Get current tenant from user here
// Make sure its a string
const tenantId = user.organization._id.toString()
setCurrentTenantId(tenantId);
next();
});
/lib/multiTenant.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const storage = require('./storage');
const GetCurrentTenantId = storage.getCurrentTenantId
const tenantModel = function (name, schema, options) {
return (props = {}) => {
schema.add({ tenantId: String });
const Model = mongoose.model(name, schema, options);
const { skipTenant } = props;
if (skipTenant) return Model;
Model.schema.set('discriminatorKey', 'tenantId');
const tenantId = GetCurrentTenantId;
const discriminatorName = `${Model.modelName}-${tenantId}`;
const existingDiscriminator = (Model.discriminators || {})[discriminatorName];
return existingDiscriminator || Model.discriminator(discriminatorName, new Schema({}));
};
}
const tenantlessModel = function (name, schema, options) {
return () => mongoose.model(name, schema, options);
}
module.exports={
tenantModel:function(){},
tenantlessModel:function(){}
}
Modified Schema
// Employee schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Tenant= require('../lib/multiTenant')
const TenantModel=Tenant.tenantModel;
//create Schema
const EmployeeSchema = new mongoose.Schema({
name: String,
department: String,
origin: String,
wages:Number,
overtime:{type:Number,
default:0},
joinDate: String,
attendances: Object
},{timestamps:true});
const Employee=TenantModel("Employee", EmployeeSchema,'employee001');
module.exports=Employee
Usage
// #desc Get all Employee
//#routes Get/api/v1/employee
//#acess Public
exports.getAllEmployee = asyncHandler(async (req, res, next) => {
Employee().find({}, null, {sort: {name: 1}}, function(err, employees){
if(err){
res.status(500);
res.send(err);
} else {
res.json(employees);
}
});
});