I'm running this on Firebase Cloud Functions, soin my index.js,I have the following snippet of code:
const admin = require("firebase-admin");
const functions = require("firebase-functions");
const usersApi = require("./api/users")
const paymentsApi = require("./api/payments")
const express = require('express');
const cors = require('cors');
const app = express();
const checkHeader = async(req, res, next) => {
if(req.headers.authorization) {
admin.auth().verifyIdToken(req.headers.authorization)
.then(token => {
req.uid = token.uid;
req.email = token.email;
req.stripeID = token.stripeID || null;
return next();
})
.catch(e => {
return next(e.errorInfo.code)
})
} else {
return next('No token found');
}
}
app.use(cors({origin: true}));
app.use(express.urlencoded({extended: true}));
app.use(express.json());
//app.use(checkHeader);
app.disable("x-powered-by");
app.use("/users", usersApi)
app.use("/payments", paymentsApi)
exports.api = functions.https.onRequest(app)
and then in my usersApi route:
const express = require('express');
const userRouter = express.Router();
const fb = require('../../fb');
const db = fb.firestore()
userRouter.post('/addUser', (req, res) => {
return db.collection('users').doc(req.uid).set({
activeSub: false,
name: req.body.name
})
.catch(err => {
throw new functions.https.HttpsError('unknown', err.message, {success:false, error: {err}})
})
})
userRouter.post("*", (req, res) => {
res.status(404).send("This route does not exist in userRouter");
})
module.exports = userRouter;
No problems here. I can POST to domain.com/api/users/addUser and I can access that function.
My payments route though doesn't seem to resolve:
const express = require('express');
const paymentRouter = express.Router();
const functions = require("firebase-functions");
const fb = require('../../fb');
const db = fb.firestore()
const stripe = require('stripe')('.....');
paymentRouter.post('/createSubscription'), (req, res) => {
return stripe.subscriptions.create({
customer: req.body.userData.stripeID,
items: [{plan: req.body.plan}]
})
.then((customer) => {
console.log('then')
console.log(customer)
return db.collection('users').doc(req.uid)
.update({
stripeID: customer.id,
activeSub: true
})
})
.catch(e => {
console.log(e)
throw new functions.https.HttpsError('unknown', err.message, e);
})
}
paymentRouter.post('/createUser'), (req, res) => {
console.log('creating user')
return stripe.customers.create({
email: req.email,
source: req.body.token
})
.then(customer => {
console.log(customer)
return db.collection('users').doc(req.uid)
.update({
stripeID: customer.id,
activeSub: true
})
})
.catch(e => {
throw new functions.https.HttpsError('unknown', err.message, e);
})
}
paymentRouter.post("*", (req, res) => {
res.status(404).send("This route does not exist in paymentRouter");
})
module.exports = paymentRouter;
Whenever I send a POST request to domain.com/api/payments/createSubscription or /createUser, it always returns 404 with This route does not exist in paymentRouter"
Can anyone explain why?
Change paymentRouter.post('/createSubscription'), (req, res) => {
to
paymentRouter.post('/createSubscription', (req, res) => {
return stripe.subscriptions.create({
customer: req.body.userData.stripeID,
items: [{plan: req.body.plan}]
})
.then((customer) => {
console.log('then')
console.log(customer)
return db.collection('users').doc(req.uid)
.update({
stripeID: customer.id,
activeSub: true
})
})
.catch(e => {
console.log(e)
throw new functions.https.HttpsError('unknown', err.message, e);
})
}
Change paymentRouter.post('/createUser'), (req, res) => {
paymentRouter.post('/createUser', (req, res) => {
console.log('creating user')
return stripe.customers.create({
email: req.email,
source: req.body.token
})
.then(customer => {
console.log(customer)
return db.collection('users').doc(req.uid)
.update({
stripeID: customer.id,
activeSub: true
})
})
.catch(e => {
throw new functions.https.HttpsError('unknown', err.message, e);
})
}
Related
Hello then i try to create new user i get error "message": "userdb validation failed: email: Path email is required."
cannot find there is a bad code field
controller.js
const { response } = require('express');
let Userdb = require('../model/model');
// create and save new user object
exports.create = (req, res) => {
// validate requast
if (!req.body) {
res.status(400).send({ message: 'Laukas negali būti tusčias!' });
return;
}
// new user
const user = new Userdb({
name: req.body.name,
email: req.body.email,
gender: req.body.gender,
status: req.body.status,
});
// save user to database
user
.save(user)
.then((data) => {
//res.send(data)
res.redirect('/add-user');
})
.catch((err) => {
res.status(500).send({
message: err.message || 'Kuriant kūrimo operaciją įvyko klaida',
});
});
};
// retrieve and ruturn all users
exports.find = (req, res) => {
Userdb.find();
if (req.query.id) {
const id = req.query.id;
Userdb.findById(id)
.then((data) => {
if (!data) {
res.status(404).send({ message: 'Nerastas naudotojas su id' + id });
} else {
res.send(data);
}
})
.catch((err) => {
res.status(500).send({ message: 'Error gaunant naudojo id' + id });
});
} else {
Userdb.find()
.then((user) => {
res.send(user);
})
.catch((err) => {
res
.status(500)
.send({
message:
err.message || 'Gaunant naudotojo informaciją įvyko klaida',
});
});
}
};
// update a new user by id
exports.update = (req, res) => {
if (!req.body) {
return res
.status(400)
.send({ message: 'Atnaujinant duomenis laukai negali būti tušti!' });
}
const id = req.params.id;
Userdb.findByIdAndUpdate(id, req.body, { useFindAndModify: false })
.then((data) => {
if (!data) {
res
.status(404)
.send({
message: `Negalima atnaujinti naudotojo su ${id}.Naudotojas nerastas!`,
});
} else {
res.send(data);
}
})
.catch((err) => {
res.status(500).send({ message: 'Error atnaujinti nepavyko' });
});
};
// Delete a user with user id
exports.delete = (req, res) => {
const id = req.params.id;
Userdb.findByIdAndDelete(id)
.then((data) => {
if (!data) {
res
.status(404)
.send({ message: `Negalima ištrinti su id ${id}. Blogas id` });
} else {
res.send({
message: 'Naudotojas ištrintas!',
});
}
})
.catch((err) => {
res.status(500).send({
message: 'Negalima ištrinti naudotojo su id=' + id,
});
});
};
model.js;
const mongoose = require('mongoose');
let schema = new mongoose.Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
gender: String,
status: String,
});
const Userdb = mongoose.model('userdb', schema);
module.exports = Userdb;
router.js;
const express = require('express');
const route = express.Router();
const services = require('../services/render');
const controller = require('../controller/controller');
/**
* #description Root Route
* #method GET/
*/
route.get('/', services.homeRoutes);
/**
* #description add users
* #method GET/ add-user
*/
route.get('/add-user', services.add_user);
/**
* #description for update user
* #method GET/ update-user
*/
route.get('/update-user', services.update_user);
// API
route.post('/api/users', controller.create);
route.get('/api/users', controller.find);
route.put('/api/users/:id', controller.update);
route.delete('/api/users/:id', controller.delete);
module.exports = route;
render.js;
const axios = require('axios');
exports.homeRoutes = (req, res) => {
// Make a get request to api users
axios
.get('http://localhost:3000/api/users')
.then(function (response) {
res.render('index', { users: response.data });
})
.catch((err) => {
res.send(err);
});
};
exports.add_user = (req, res) => {
res.render('add_user');
};
exports.update_user = (req, res) => {
res.render('update_user');
};
connection.js;
const mongoose = require('mongoose');
const connectDB = async () => {
try {
//mongoDB connection string
const con = await mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
console.log(`MongoDB connected: ${con.connection.host}`);
} catch (err) {
console.log(err);
process.exit(1);
}
};
module.exports = connectDB;
server.js;
const express = require('express');
const dotenv = require('dotenv');
const morgan = require('morgan');
const bodyparser = require('body-parser');
const path = require('path');
const connectDB = require('./server/database/connection');
const app = express();
dotenv.config({ path: 'config.env' });
const PORT = process.env.PORT || 8080;
//log requests
app.use(morgan('tiny'));
// mongoDB connection
connectDB();
// parse request to body-parses
app.use(bodyparser.urlencoded({ extended: true }));
//set view engine
app.set('view engine', 'ejs');
//app.set("views",path.resolve(__dirname,"views/ejs"))
//load assets
app.use('/css', express.static(path.resolve(__dirname, 'assets/css')));
app.use('/img', express.static(path.resolve(__dirname, 'assets/img')));
app.use('/js', express.static(path.resolve(__dirname, 'assets/js')));
//css/style.css
//load routes
app.use('/', require('./server/routes/router'));
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
add this middleware app.use(bodyParser.json());
upper of app.use(bodyparser.urlencoded({extended:true}))
to get data from front
I am getting Error: next is not defined. I don't know in which file I am getting this error.
Code:
server.js
require("dotenv").config({
path: "C:/Users/dogra/Documents/Web Development/Portfolio/FullStack/AdvanceAuth/.env",
});
const express = require("express");
const connectDB = require("./config/db");
const errorHandler = require("./middleware/errorHandler");
connectDB();
const app = express();
app.use(express.json());
app.use("/api/auth", require("./routes/authRoutes"));
app.use("/api/private", require("./routes/privateRoutes"));
app.use(errorHandler);
const PORT = process.env.PORT || 5000;
const server = app.listen(PORT, () => {
console.log(`Server running on PORT: ${PORT}`);
});
process.on("unhandledRejection", (err, promise) => {
console.log(`Logged Error: ${err.message}`);
server.close(() => process.exit(1));
});
controllers
authController.js
const User = require("../models/userModel");
const ErrorResponse = require("../utils/errorResponse");
exports.register = async (req, res, next) => {
const { username, email, password } = req.body;
try {
const user = await User.create({
username,
email,
password,
});
sendToken(user, 201, res);
} catch (error) {
next(error);
}
};
exports.login = async (req, res, next) => {
const { email, password } = req.body;
if (!email || !password) {
return next(new ErrorResponse("Please enter credentials properly", 400));
}
try {
const user = await User.findOne({ email }).select("+password");
if (!user) {
return next(new ErrorResponse("Email not registered", 401));
}
const isMatch = await user.matchPasswords(password);
if (!isMatch) {
return next(new ErrorResponse("Invalid Password", 401));
}
sendToken(user, 200, res);
} catch (error) {
next();
}
};
exports.forgotPassword = (req, res, next) => {
res.send("ForgotPassword Route");
};
exports.resetPassword = (req, res, next) => {
res.send("ResetPassword Route");
};
const sendToken = (user, statusCode, res) => {
const token = user.getSignedJwtToken();
res.status(statusCode).json({ success: true, token });
};
privateController.js
exports.private = (req, res, next) => {
res.status(200).json({
success: true,
data: "You got access to the private data in this route",
});
};
routes
authRoutes.js
const express = require("express");
const router = express.Router();
// controllers
const {
register,
login,
forgotPassword,
resetPassword,
} = require("../controllers/authControllers");
router.route("/register").post(register);
router.route("/login").post(login);
router.route("/forgotPassword").post(forgotPassword);
router.route("/resetPassword/:resetToken").put(resetPassword);
module.exports = router;
privateRoutes.js
const express = require("express");
const router = express.Router();
const { private } = require("../controllers/privateControllers");
const { protect } = require("../middleware/authMiddleware");
router.route("/").get(protect, private);
module.exports = router;
middlewre
authMiddleware.js
const jwt = require("jsonwebtoken");
const User = require("../models/userModel");
const ErrorResponse = require("../utils/errorResponse");
exports.protect = async (req, res, next) => {
let token;
if (
req.headers.authorization &&
req.headers.authorization.startsWith("Bearer")
) {
token = req.headers.authorization.split(" ")[1];
}
if (!token) {
return next(
new ErrorResponse("Not authorized to access to this route", 401)
);
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const user = await User.findById(decoded.id);
if (!user) {
return next(new ErrorResponse("No User found with this id", 404));
}
req.user = user;
next();
} catch (error) {
return next(new ErrorResponse("Not Authorized to access this route", 401));
}
};
errorHandler.js
const ErrorResponse = require("../utils/errorResponse");
const errorHandler = (err, req, res, next) => {
let error = { ...err };
error.message = err.message;
if (err.code === 11000) {
const message = `Duplicate Field value entered`;
error = new ErrorResponse(message, 400);
}
if (err.name === "ValidationError") {
const message = Object.values(err.errors).map((val) => val.message);
error = new ErrorResponse(message, 400);
}
console.log(error.message);
res.status(error.statusCode || 500).json({
success: false,
error: error.message || "Server Error",
});
};
module.exports = errorHandler;
utils
errorResponse.js
class ErrorResponse extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
}
}
module.exports = ErrorResponse;
models
userModel.js
const mongoose = require("mongoose");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const UserSchema = new mongoose.Schema({
username: {
type: String,
required: [true, "Please enter your username"],
},
email: {
type: String,
required: [true, "Please enter your email"],
unique: true,
lowercase: true,
match: [
/^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
,
"Please provide a valid email",
],
},
password: {
type: String,
required: [true, "Please enter a valid password"],
minlength: 8,
select: false,
},
resetPasswordToken: String,
resetPasswordExpired: Date,
});
// Hashing Password
UserSchema.pre("save", async function (next) {
if (!this.isModified("password")) {
next();
}
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
next();
});
// Checking if password entered is correct or not
UserSchema.methods.matchPasswords = async function (password) {
return await bcrypt.compare(password, this.password);
};
// Converting user data into JSON WEB TOKEN
UserSchema.methods.getSignedJwtToken = function () {
return jwt.sign({ id: this._id }, process.env.JWT_SECRET, {
expiresIn: process.env.JWT_EXPIRE,
});
};
const User = mongoose.model("User", UserSchema);
module.exports = User;
Sorry, for the long question but I really don't know where is the problem. I googled, & found we get next is not defined error when you don't define it source. But, I have defined it inside my all controllers & middleware's.
The problem was in my dotenv path in server.js Since I cloned my project from GitHub in my new laptop the path was different & I forgot to update the path.
I send request from React with:
export const loadItems = () => async dispatch => {
await axios
.get("http://localhost:8000/api/users")
.then(response => {
console.log(response.users);
dispatch(dataLoaded(response.users));
})
.catch(err => {
dispatch(dataLoadFailed(err));
});
};
But there is no response, and the server does not take request, here is my server app code:
server.js
// a lot of requires
const todoRoutes = require("./routes/serverRoute");
const url = "mongodb://localhost:27017/taskManager";
const app = express();
mongoose.Promise = global.Promise;
mongoose.connect(
url,
{ useNewUrlParser: true },
function(err) {
if (err) {
console.log(err);
} else console.log("Database connected");
}
);
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "/public/index.html"));
});
// cors allow
app.use("/api", todoRoutes);
app.listen(8000, () => {
console.log("API started");
});
And this is a controller I use, it's all good with Schema and DB, I checked with output to console from the node, users is defined and contains data
const mongoose = require("mongoose");
const User = require("../models/UserModel");
module.exports = {
getUsers(req, res) {
User.find().exec((err, users) => {
if (err) {
console.log(err);
return res.send({ err });
} else {
console.log(users);
return res.send({ users });
}
});
}
};
And this is my router:
module.exports = router => {
router.get('/users', userController.getUsers);
}
Ok, I got it on my own. Problem was here:
router.get('/users', userController.getUsers);
It supposed to be like this:
router.get('/users', userController.getUsers());
I'm currently having an issue with figuring out how I can access req.user so I can get the logged in users id and save it with the items that they save on the web page. That way when they load the web page they only get their items. The only place I know where I have access to req.user is in my /router/auth.js file. I want to figure out a way to access it in a different router file.
router/auth.js
const express = require('express');
const passport = require('passport');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');
const config = require('../config');
const router = express.Router();
const createAuthToken = function (user) {
return jwt.sign({ user }, config.JWT_SECRET, {
subject: user.username,
expiresIn: config.JWT_EXPIRY,
algorithm: 'HS256'
});
};
const localAuth = passport.authenticate('local', { session: false });
router.use(bodyParser.json());
router.post('/login', localAuth, (req, res) => {
const authToken = createAuthToken(req.user.serialize());
res.json({ authToken });
});
const jwtAuth = passport.authenticate('jwt', { session: false });
router.post('/refresh', jwtAuth, (req, res) => {
const authToken = createAuthToken(req.user);
res.json({ authToken });
});
/router/portfolio.js
router.post('/:id', (req, res) => {
const id = req.params.id;
const { holdings } = req.body;
CryptoPortfolio.findOne({ id }, (err, existingCoin) => {
if (existingCoin === null) {
getCoins(id)
.then(x => x[0])
.then(value =>
CryptoPortfolio.create({
id: value.id,
holdings,
_creator: this is where I want to add req.user.id
}).then(() => value))
.then(newItem => {
res.status(201).json(newItem);
})
.catch(err => {
console.error(err);
res.status(500).json({ message: 'Internal server error' });
});
} else {
const capitalizedId = id.charAt(0).toUpperCase() + id.slice(1);
res.json(`${capitalizedId} already in watchlist`);
}
});
});
You can define global variable and use it using middleware.
app.js
// Global Vars
app.use(function (req, res, next) {
res.locals.user = req.user
next();
});
route.js
router.get('/', function(req, res) {
CryptoPortfolio.find({}, function(err, crypto) {
console.log('CryptoPortfolio : ',crypto);
res.render('view/crypto', {
user : res.locals.user // <= here
});
});
});
I hope it would be helpful :)
I figured out that I wasn't using the code below on any of the necessary routes. Implemented it and I can now access req.user.
const jwtAuth = passport.authenticate('jwt', { session: false });
My get and post APIs are working, but for some reason my app.put isn't.
When I hit localhost:3001/contacts/1 as a PUT in PostMan, I don't even see my simple console.log:
app.put('/api/contacts:id', (req, res) => {
console.log('req.params.id', req.params.id);
res.json(contact);
});
app.put
app.put('/api/contacts:id', (req, res) => {
console.log('req.params.id', req.params.id);
res.json(contact);
});
Full server.js code
// Requires ////////////////////////////////////////////////////////////////////
const express = require('express');
const app = express();
const bodyParser = require('body-parser'); // req.body
const cors = require('cors');
const R = require('ramda');
// Variables ///////////////////////////////////////////////////////////////////
const hostname = 'localhost';
const port = 3001;
let contacts = require('./data');
// Logic ///////////////////////////////////////////////////////////////////////
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors());
app.get('/api/contacts', (req, res) => {
if (!contacts || R.isEmpty(contacts)) returnError(res, 'No Contacts found');
res.json(contacts);
});
app.get('/api/contacts/:id', (req, res) => {
const contact = contacts.filter(contact => contact.id == req.params.id);
if (R.isEmpty(contact)) returnError(res, 'No Contact found');
res.json(R.head(contact));
});
app.post('/api/contacts', (req, res) => {
const contact = {
id: contacts.length + 1,
first_name: req.body.first_name,
last_name: req.body.last_name,
email: req.body.email,
website: req.body.website
}
contacts.push(contact);
res.json(contact);
});
app.put('/api/contacts:id', (req, res) => {
console.log('req.params.id', req.params.id);
// const contact = contacts.filter(contact => {
// return contact.id == req.params.id
// })[0];
// console.log('1 contact', contact);
// const index = contacts.indexOf(contact);
// const keys = Object.keys(req.body);
// keys.forEach(key => {
// contact[key] = req.body[key];
// });
// console.log('2 contact', contact);
// contacts[index] = contact;
// console.log('contacts', contacts);
// res.json(contacts[index]);
res.json(contact);
});
const returnError = (res, msg) => res.status(404).json({ message: msg });
app.listen(port, hostname, () => {
console.log(`server is running at http://${hostname}:${port}`);
});
Looks like a typo in this line:
app.put('/api/contacts:id', (req, res) => {
Add a '/' to read:
app.put('/api/contacts/:id', (req, res) => {
Your URL looks like this:
app.put('/api/contacts:id', (req, res) => {,
But it should be like this:
app.put('/api/contacts/:id', (req, res) => {