I'm still having some exception errors about JSON web token Private Key. It says it's not defined but I think I already put the JSON web token private key and still throwing an error. I'm not sure where the problem is maybe in the user module or auth module or on the config. Please see the below code and any help would be appreciated.
//default.json
{
"jwtPrivateKey": "",
"db": "mongodb://localhost/vidly"
}
// test.json
{
"jwtPrivateKey": "1234",
"db": "mongodb://localhost/vidly_tests"
}
// config.js
const config = require('config');
module.exports = function() {
if (!config.get('jwtPrivateKey')) {
throw new Error('FATAL ERROR: jwtPrivateKey is not defined.');
}
}
// users.js
const auth = require('../middleware/auth');
const jwt = require('jsonwebtoken');
const config = require('config');
const bcrypt = require('bcrypt');
const _ = require('lodash');
const {User, validate} = require('../models/user');
const mongoose = require('mongoose');
const express = require('express');
const router = express.Router();
router.get('/me', auth, async (req, res) => {
const user = await User.findById(req.user._id).select('-password');
res.send(user);
});
router.post('/', async (req, res) => {
const { error } = validate(req.body);
if (error) return res.status(400).send(error.details[0].message);
let user = await User.findOne({ email: req.body.email });
if (user) return res.status(400).send('User already registered.');
user = new User(_.pick(req.body, ['name', 'email', 'password']));
const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(user.password, salt);
await user.save();
const token = user.generateAuthToken();
res.header('x-auth-token', token).send(.pick(user, ['id', 'name', 'email']));
});
module.exports = router;
// auth.js
const Joi = require('joi');
const bcrypt = require('bcrypt');
const _ = require('lodash');
const {User} = require('../models/user');
const mongoose = require('mongoose');
const express = require('express');
const router = express.Router();
router.post('/', async (req, res) => {
const { error } = validate(req.body);
if (error) return res.status(400).send(error.details[0].message);
let user = await User.findOne({ email: req.body.email });
if (!user) return res.status(400).send('Invalid email or password.');
const validPassword = await bcrypt.compare(req.body.password, user.password);
if (!validPassword) return res.status(400).send('Invalid email or password.');
const token = user.generateAuthToken();
res.send(token);
});
function validate(req) {
const schema = {
email: Joi.string().min(5).max(255).required().email(),
password: Joi.string().min(5).max(255).required()
};
return Joi.validate(req, schema);
}
module.exports = router;
// db.js
const winston = require('winston');
const mongoose = require('mongoose');
const config = require('config');
module.exports = function() {
const db = config.get('db');
mongoose.connect(db)
.then(() => winston.info(Connected to ${db}...));
}
// logging.js
const winston = require('winston');
// require('winston-mongodb');
require('express-async-errors');
module.exports = function() {
winston.handleExceptions(
new winston.transports.Console({ colorize: true, prettyPrint: true }),
new winston.transports.File({ filename: 'uncaughtExceptions.log' }));
process.on('unhandledRejection', (ex) => {
throw ex;
});
winston.add(winston.transports.File, { filename: 'logfile.log' });
// winston.add(winston.transports.MongoDB, {
// db: 'mongodb://localhost/vidly',
// level: 'info'
// });
}
// index.js
const winston = require('winston');
const express = require('express');
const app = express();
require('./startup/logging')();
require('./startup/routes')(app);
require('./startup/db')();
require('./startup/config')();
require('./startup/validation')();
const port = process.env.PORT || 3000;
app.listen(port, () => winston.info(Listening on port ${port}...));
// user.test.js
const {User} = require('../../../models/user');
const jwt = require('jsonwebtoken');
const config = require('config');
const mongoose = require('mongoose');
describe('user.generateAuthToken', () => {
it('should return a valid JWT', () => {
const payload = {
_id: new mongoose.Types.ObjectId().toHexString(),
isAdmin: true
};
const user = new User(payload);
const token = user.generateAuthToken();
const decoded = jwt.verify(token, config.get('jwtPrivateKey'));
expect(decoded).toMatchObject(payload);
});
});
// package.json
"scripts": {
"test": "jest --watchAll --verbose"
},
the structure of your config files are wrong. if u check the https://www.npmjs.com/package/config
this is the structure of file:
{
"Customer": {
"dbConfig": {
"host": "prod-db-server"
},
"credit": {
"initialDays": 30
}
}
}
that page also provides this info:
config.get() will throw an exception for undefined keys to help catch typos and missing values. Use config.has() to test if a configuration value is defined.
I think set does not work with visual studio code terminal. I had same issue, when i executed in Windows CMD it worked.
Try config.get instead of config.has()
module.exports = function() {
if (!config.has('jwtPrivateKey')) {
throw new Error('FATAL ERROR: jwtPrivateKey is not defined.');
}
if you are using mosh's tutorial as it said here you should have a file named custom-environment-variables.json too and it contains:
{
"jwtPrivateKey": "vidly_jwtPrivateKey"
}
then you have to set an environment variable called vidly_jwtPrivateKey.
in windows you can run this: set vidly_jwtPrivateKey=mySecureKey on CMD.
Hope it solves the problem :)
n
if(!config.has('jwtPrivateKey')) {
console.error("FATAL ERROR: jwtPrivateKey not defined.")
process.exit(1);
}
try to use config.has() instead of config.get()
Related
Javascript says that my variables which are in .env are undefined. I've installed dotenv but it doesn't work.
My index.js
const express = require("express");
const mongoose = require("mongoose");
const app = express();
const router = express.Router();
const port = process.env.PORT || 5000;
const dotenv = require("dotenv");
const userRoute = require('./routes/user');
const authRoute = require('./routes/auth');
mongoose.set('strictQuery', false);
dotenv.config();
mongoose
.connect(
process.env.MONGODB_URL
)
.then(() => console.log("Database is working"))
.catch((err) => {
console.log(err)
});
app.use(express.json());
app.use('', authRoute);
app.listen(process.env.PORT, function () {
console.log('Server is up on port ' + process.env.PORT)
})
My auth.js
const router = require('express').Router();
const User = require('../models/user');
const Crypto = require('crypto-js');
const { response } = require('express');
const secretKey = process.env.SECRET_KEY;
// Create a registration
console.log(secretKey);
router.post('/rejestracja', async (req, res)=>{
const nowyUser = new User({
email: req.body.email,
password: Crypto.AES.encrypt(req.body.password, process.env.SECRET_KEY).toString(),
firstName: req.body.firstName,
surname: req.body.surname,
username: req.body.username,
});
try{
const newedUser = await nowyUser.save();
res.status(201).json(newedUser);
}
catch(err){res.status(500).json(err)};
})
// Create a login
router.post('/login', async (req, res) => {
try{
const user = await User.findOne({email: req.body.email});
if (!user) {
return res.status(401).json("i/lub hasło jest nieprawidłowy");
}
const securedPass = Crypto.AES.decrypt( user.password, "a");
const password = securedPass.toString(Crypto.enc.Utf8);
console.log(password);
if (password !== req.body.password) {
res.status(401).json("Email i/lub hasło jest nieprawidłowy");
}else {
res.status(200).json(user);
}
}
catch(err) {
res.status(500).json({message: err.message});
}
});
module.exports = router
And my .env
MONGODB_URL = mongodb+srv://someInterestingWords
PORT = 5500
SEC_KEY = a
Everything works when these variables are in my code, not in .env.
I've tried to delete dotenv and add it again but id doesn't change anything.
process.env.something works in index.js but it doesn't in other files
My project file structure
At the moment you doing require, Node.JS executing specified file (or importing lib).
Now let's look at first lines of Your code:
const dotenv = require("dotenv");
const userRoute = require('./routes/user');
const authRoute = require('./routes/auth');
mongoose.set('strictQuery', false);
dotenv.config();
You may notice: first you doing require on ./routes/user and ./routes/auth, then you doing dotenv.config().
You need to do dotenv.config() Before using process.env, so try next:
const express = require("express");
const mongoose = require("mongoose");
const app = express();
const router = express.Router();
/*
Doing `config` just after `require`.
Also, in most cases, You don't need dotenv after using this once,
so no need to store `dotenv` constant.
*/
require("dotenv").config();
const port = process.env.PORT || 5000;
const userRoute = require('./routes/user');
const authRoute = require('./routes/auth');
// other lines...
Also notice, if .env file locates not in __dirname (directory, where launches main file), you need to specify it's location:
require('dotenv').config({path: '../configs/.env'});
or using path:
const path = require('path');
require('dotenv').config({path: path.join(__dirname, '../configs/.env')});
I have some simple javascript code in three files. There is my server.js, which has
const userRouter = require('./routes/users')
app.use("/",userRouter)
Then there is my middleware users.js with
module.exports = router
and lastly user.js with
module.exports = {
User:User,
validateLogin:validateUserLogin,
validateRegister:validateUserRegister,
}
When my user.js had just the export line module.exports = User my code worked just fine. server.js imports users.js, which imports user.js. But when exporting functions along with my User object, my requests stop working. Why? How can I fix this? I'm using Node.js with express and mongo db. All my HTML requests are in users.js.
The code to my server.js is
const express = require('express');
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
//just show server is running
const app = express()
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
const PORT = 4000;
app.get("/status", async (req, res) => {
return res.status(400).send("server for GET is running");
});
app.post("/status", async (req, res) => {
return res.status(200).send({
status: "server for POST is running",
message: req.body.message
});
});
app.listen(PORT, function() {
console.log(`server running on port ${PORT}`);
});
const url = "mongodb+srv://Admin:strongpassword#cluster0.tjual.mongodb.net/ConfusedTom?retryWrites=true&w=majority"
mongoose.connect(url, {
useNewUrlParser: true,
useUnifiedTopology: true,
dbName: "ConfusedTom"
}).then(() => {
console.log("connected successfully to server, using database %s\n", mongoose.connection.$dbName);
}).catch(err => {
console.log(err);
});
const userRouter = require('./routes/users')
app.use("/",userRouter)
and here is my users.js
const mongoose = require("mongoose");
const express = require("express");
const router = express.Router();
const ObjectId = mongoose.Types.ObjectId;
const Review = require("../models/review.js")
const TVShow = require("../models/tvshows.js")
const { User, validateLogin, validateRegister} = require("../models/user.js")
router.get("/username", async (req, res) => {
console.log("reached!")
var user = await User.findOne({ username: req.body.username });
if (!user) return res.status(400).send("User doesn't exist.");
return res.status(200).send(user)
});
router.post("/register", async(req,res) => {
const { error } = validateRegister(req.body);
if (error) return res.status(400).send(error.details[0].message);
else user = await User.findOne({ username: req.body.username });
if (user) return res.status(400).send("Username already taken.");
//create new user
user = new User({
firstName: req.body.firstName,
lastName: req.body.lastName,
username: req.body.username,
password: req.body.password,
});
user.save();
return res.status(200).send("User registered successfully.");
})
router.post("/login", async (req, res) => {
console.log("reached!")
// validate the request body first
const { error } = validateLogin(req.body);
if (error) return res.status(400).send(error.details[0].message);
//find an existing user
var user = await User.findOne({ username: req.body.username });
if (!user) return res.status(400).send("Username reqired.");
if (user) {
if (user.validatePassword(req.body.password)) {
return res.header.status(200).send("User login successfully");
}
else return res.status(400).send("Password is incorrect");
} else return res.status(400).send("User doesn't exist.");
});
module.exports = router
The problem with your updated import of the stuff from user.js is you're using the wrong names for the functions. You currently have:
const UserStuff = require("../models/user.js")
const User = UserStuff.User;
const validateLogin = UserStuff.validateUserLogin;
const validateregister = UserStuff.validateUserRegister;
but the object you're exporting is:
module.exports = {
User:User,
validateLogin:validateUserLogin,
validateRegister:validateUserRegister,
}
You're using the wrong names of the functions (validateUserLogin instead of validateLogin). The names you use have to match at both ends. So:
const UserStuff = require("../models/user.js")
const User = UserStuff.User;
const validateLogin = UserStuff.validateLogin;
// ^^^^^^^^^^^^^
const validateregister = UserStuff.validateRegister;
// ^^^^^^^^^^^^^^^^
or more concisely:
const { User, validateLogin, validateRegister} = require("../models/user.js")
I cannot get my post meetingtype route to work. the problem seems to be between my model and my DAO as some of my code tweaking got MeetingType.create is not a function errors. Currently I just get Cannot POST /api/meetingtype in insomnia. The Sequelize create is not a function answers on stack overflow arn't helping. Here is my code:
//database/index
const { Sequelize } = require('sequelize');
const DB = new Sequelize({
dialect: 'sqlite',
storage: 'C:/Users/bubblegum/Desktop/programming projects/Oconnell/database/db.db',
define: {timestamps: false}
}
);
module.exports.DB = DB;
//models/meetingtype.js
'use strict';
const DB = require('../database/index');
const { Sequelize, Model, DataTypes, INTEGER} = require('sequelize');
module.exports = (DB, DataTypes) => {
class MeetingType extends Model {
static associate(models) {
// define association here
}
};
MeetingType.init({
MeetingTypeID: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
MeetingTypeDescription: DataTypes.STRING
}, {
DB,
modelName: 'MeetingType',
});
return MeetingType;
};
/DAO/MeetingTypeDAO.js
const Sequelize = require('sequelize'); // attempt to get create to work
const DB = require('../database/index').DB;
const MeetingType = require('../models/MeetingType');
var MeetingTypeDao = {
create: create
}
function create(MeetingType) {
MeetingType.create(MeetingType).then(NewMeetingType => { //MeetingType is json of not autoincrement properties
return NewMeetingType;
});
}
module.exports = MeetingTypeDao;
//controllers/MeetingTypeController.js
const MeetingTypeDao = require('../DAO/MeetingTypeDao');
var MeetingTypeController = {
addMeetingType: addMeetingType
}
function addMeetingType(req, res) {
MeetingTypeDao.create(req.body). //json of non autoincrement MeetingType properties
then((MeetingType) => {
res.send(MeetingType);
})
.catch((error) => {
console.log(error);
});
}
module.exports = MeetingTypeController;
//routers/MeetingTypeRouter
const Express = require('express');
const router = Express.Router();
const MeetingTypeController = require('../Controllers/MeetingTypeController');
router.post('/', MeetingTypeController.addMeetingType);
module.exports = router;
//app.js
const Express = require('express');
const { Sequelize } = require('sequelize');
const {DB} = require('./database');
let app = Express();
const MeetingTypeRouter = require('./routers/MeetingTypeRouter');
app.use(Express.urlencoded({ extended: true }));
app.use(Express.json());
app.use('api/meetingtype', MeetingTypeRouter);
DB.authenticate().then(()=>{
console.log('Connection has been established successfully.');
}).catch(err => console.log("Error: " + err));
const PORT = process.env.PORT || 3000;
try {
app.listen(PORT, console.log(`Server started on port ${PORT}`));
} catch (error) {
console.log("Error: " + error);
};
this is my app.js
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const mongoose = require("mongoose");
const inputRoutes = require("./routes/input");
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors());
app.use(cors());
app.use((req, res, next) => {
res.setHeader("Acess-Control-Allow-Origin", "*");
res.setHeader(
"Acess-Control-Allow-Methods",
"OPTIONS ,GET ,POST ,PUT,PATCH , DELETE"
);
res.setHeader("Acess-Control-Allow-Headers", "Content-Type, Authorization");
next();
});
app.use("/input", inputRoutes);
mongoose
.connect("mongodb://localhost:27017/MEAN", { useNewUrlParser: true })
.then(result => {
app.listen(2400);
})
.catch(err => console.log(err));
this is my routes/input.js
const express = require("express");
const router = express.Router();
const inputController = require("../controller/input");
router.post("/todo", inputController.createTodos);
module.exports = router;
this is my controller,input.js
const Todo = require("../models/todos");
const { validationResult } = require("express-validator/check");
exports.createTodos = (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
const error = new Error("validation failed due to incorrect data");
error.statusCode = 442;
throw error;
}
const task = req.body.task;
const status = req.body.status;
console.log(task);
console.log(status);
const todo = new Todo({
task: task,
status: status
});
todo
.save()
.then(result => {
console.log(task);
res.status(201).json({
message: "post created sucessfully",
post: result
});
})
.catch(err => {
if (!err.statusCode) {
err.statusCode = 500;
}
next(err);
});
};
this is my model.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const todoSchema = new Schema(
{
task: {
type: String,
required: true
},
status: {
type: Boolean,
default: false
}
},
{ timestamps: true }
);
module.exports = mongoose.model("Todo", todoSchema);
You need to send JSON request in the postman first choosing raw option, and then json in the right dropdown.
Also you seem to use express-validator package, but you don't use it in router.
In the router you can use it like this:
const express = require("express");
const router = express.Router();
const { check } = require("express-validator");
const inputController = require("../controller/input");
router.post("/todo", [
check("task")
.not()
.isEmpty()
], inputController.createTodos);
module.exports = router;
Also in controller you should import the validationResult from express-validator,
and validate the result like this:
const { validationResult } = require('express-validator');
exports.createTodos = (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.array() });
}
....
}
I have a working codebase where they have already setup node proxy and jwt.
my server is running at 1010 port
but when I hit this url http://localhost:1010/sampletest
I am getting an error in the browser screen Cannot GET /sampletest
even I hit this url http://localhost:1010/jump/api/v1 but still I am getting same error
can you tell me how to fix it or am I missing anthing in the configurations
providing my index.js and server.js code below
sports.js
const express = require('express');
const axios = require('axios');
const mime = require('mime-types');
const router = express.Router();
const ResponseUtil = require('../../utils/ResponseUtil');
const AppConstants = require('../../../constants/AppConstants');
const credentials = require('../../../internals/credentials.json');
const memberGroupingHelper = require('../../helpers/rank/memberGrouping');
const exportHelper = require('../../helpers/rank/rankExportHelper');
const formatExportData = require('../../helpers/rank/formatExportData');
const rankCommonHelper = require('../../helpers/rank/rankCommonHelper');
const rankProvDataHelper = require('../../helpers/group/getProvData');
//const aggregateHelper = require('../../helpers/group/aggregateFilter');
const { rankAggregatelastrsApi } = require('jump-svc-utils');
//router.get('/:searchMode/:lastrSearch', (req, res, next) => {
router.get('/sampletest', (req, res, next) => {
const { originalUrl } = req;
//console.log(" originalUrl ", originalUrl);
const mode = req.params.searchMode;
const value = encodeURIComponent(req.params.lastrSearch);
console.log("document 40--->", mode);
console.log("for document Testing0--->", mode);
const url = `/jkjkjk/sdjksdjkjksdjksd/sdklsdlksdklsdkl`;
axios.get(AppConstants.GET_JWT_TOKEN_URL, {
auth: {
username: credentials.auth.racfId, password: credentials.auth.password
}
})
.then((jwtResponse) => {
// var jwtToken = `Bearer ${jwtResponse.data.jwt}`;
var jwtToken = `Bearer 787878bjhbnmnmmwqdqwqwqwqwqwqwqwqwqwqwqwqwqwqwqwqwqwqw`;
axios.get(url, { headers: { "Authorization": jwtToken } })
.then((response) => {
console.log("document then0--->", response);
const file = Buffer.from(response.data.content, 'base64');
const fileType = mime.contentType(response.data.contentInfo.fileType);
const fileExtension = response.data.contentInfo.fileType.toLowerCase();
const fileName = `filename=${response.data.contentInfo.id}.${fileExtension}`;
res.set('Content-Type', fileType);
res.set('Content-disposition', `attachment; ${fileName}`);
res.send(file);
})
.catch((e) => {
console.log("e catch document0--->", e);
console.log("e.message catch document0--->", e.message);
console.log("catch document--->", e.response);
if (e.response) {
return res.status(e.response.status).send(e.response.data);
}
res.status(500).send(e.message || 'Something wrong');
});
});
ResponseUtil.callService(res, url);
});
module.exports = router;
index.js
const express = require('express')
const app = express()
const port = 1010
const jumpServices = require('./services/jump');
const compression = require('compression');
var BodyParser = require('body-parser');
const glob = require('glob');
const path = require('path');
app.use('/jump/api/v1', jumpServices);
app.use(BodyParser.json());
app.use(BodyParser.urlencoded({
extended: true
}));
//app.use(compress())
// app.use(compression());
// include all the controllers
const controllers = glob.sync(path.join(__dirname, '/controllers/**/*.js'));
console.log("controllers--->", controllers);
controllers.forEach((controllerFileName) => {
require(controllerFileName)(app); //eslint-disable-line
});
app.listen(port, (err) => {
if (err) {
return console.log('something bad happened', err)
}
console.log(`server is listening on ${port}`)
})
I don't see any calls registering your sub Routers with the top level express application. You should need to call app.use for each of your sub routers.