I have added a model to my frontend and backend so that users can update their profile (name age etc.), however, when I'm trying to update my test user name it's not updating, and I'm recieving the below error message in my terminalTerminal error
See below my server.js and profile.js
SERVER.JS
const express = require("express");
const bodyParser = require("body-parser");
const bcrypt = require("bcrypt-nodejs");
const cors = require("cors");
const knex = require("knex");
const register = require("./controllers/register");
const signin = require("./controllers/signin");
const profile = require("./controllers/profile");
const image = require("./controllers/image");
const { Pool } = require("pg");
const morgan = require("morgan");
const nodemailer = require("nodemailer");
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = "1";
const pool = new Pool({
connection: process.env.POSTGRES_URI,
ssl: process.env.DATABASE_URI ? true : false,
});
const db = knex({
client: "pg",
connection: process.env.POSTGRES_URI,
ssl: {
rejectUnauthorized: false,
},
});
const app = express();
app.use(bodyParser.json());
app.use(morgan("combined"));
app.use(cors());
app.get("/", (req, res) => {
res.send("it is working");
});
app.post("/signin", (req, res) => {
signin.handleSignin(req, res, db, bcrypt);
});
app.post("/register", (req, res) => {
register.handleRegister(req, res, db, bcrypt);
});
app.get("/profile/:id", (req, res) => {
profile.handleProfile(req, res, db);
});
app.post("/profile/:id", (req, res) => {
profile.handleProfileUpdate(req, res, db);
});
app.put("/image", (req, res) => {
image.handleImage(req, res, db);
});
app.post("/imageurl", (req, res) => {
image.handleApiCall(req, res);
});
app.post("/sendResetPassowrdLink", (req, res) => {
const email = req.body.email;
pool.query(`SELECT * FROM login WHERE email='${email}'`).then((data) => {
if (data.rowCount === 0) {
return res
.status(401)
.json({ message: "user with that email does not exists" });
}
const { email } = data.rows[0];
const emailBody = `your sever url is http://localhost:3001/resetpassword/${btoa(
email
)}`;
res.send(emailBody);
});
});
app.get("/resetpassword/:token", (req, res) => {
const email = atob(req.params.token);
const { newPassowrd, newPassowrdConfirm } = req.body;
if (newPassowrd !== newPassowrdConfirm) {
return res.status(400).json({ message: "passowrd does not match" });
}
const hash = bcrypt.hashSync(newPassowrd);
pool
.query(`UPDATE login SET hash='${hash}' WHERE email='${email}'`)
.then((data) => {
if (data.rowCount === 1) {
return res
.status(200)
.json({ message: "password updated successfully" });
}
});
});
const PORT = process.env.PORT || 3005;
app.listen(PORT, () => {
console.log(`app is running on port ${PORT}`);
});
PROFILE.JS
const handleProfile = (req, res, db) => {
const { id } = req.params;
db.select("*")
.from("users")
.where({ id })
.then((user) => {
if (user.length) {
res.json(user[0]);
} else {
res.status(400).json("not found");
}
})
.catch((err) => res.status(400).json("error getting user"));
};
const handleProfileUpdate = (req, res, db) => {
const { id } = req.params;
const { name, age, pet } = req.body.formInput;
db("users")
.where({ id })
.update({ name })
.then((resp) => {
if (resp) {
res.json("success");
} else {
res.status(400).json("Unable to udpate");
}
})
.catch((err) => console.log(err));
};
module.exports = {
handleProfile,
handleProfileUpdate,
};
I also recently added docker container to my backend and database, could that be the cause for the issue?
below is my github backend repo with the docker included
https://github.com/Moshe844/smartbrain-api/tree/master
Related
I'm trying to learn MERN/CRUD but running into an issue when I attempt to POST to my database. Trying to reach it via Insomniac gives me a 'cannot POST /users' error, and the console gives me a 'Unhandled Rejection (Error): Request failed with status code 404' error.
app.js
let express = require('express'),
mongoose = require('mongoose'),
dbConfig = require('./database/db'),
cors = require('cors');
const userRoute = require('./routes/user.route');
mongoose.Promise = global.Promise;
mongoose.connect(dbConfig.db, {
useNewUrlParser: true,
useUnifiedTopology: true
}).then(() => {
console.log('Connection established with database...') },
error => { console.log(`Error when connecting to database: ${error}`);
})
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use('/users', userRoute);
const port = process.env.PORT || 4000;
const server = app.listen(port, () => {
console.log(`Successfully connected on port: ${port}`)
});
Part of create-user-component.js
onSubmit(e) {
e.preventDefault();
const userObject = {
firstName: this.state.firstName,
lastName: this.state.lastName,
email: this.state.email
};
axios.post('http://localhost:4000/users', userObject)
.then(res => console.log(res.data));
this.setState({ firstName: '', lastName: '', email: '' });
}
user.route.js
let mongoose = require('mongoose'),
express = require('express'),
router = express.Router();
let userSchema = require('../models/User');
// CREATE/POST User
router.route('/users').post((req, res, next) => {
userSchema.create(req.body, (error, data) => {
if (error) {
return next(error)
} else {
console.log(data)
res.json(data)
}
})
});
router.route('/users').get((req, res) => {
userSchema.find((error, data) => {
if (error) {
return next(error);
} else {
res.json(data);
}
})
})
router.route('/users/:id').get((req, res) => {
userSchema.findById(req.params.id, (error, data) => {
if (error) {
return next(error);
} else {
res.json(data);
}
})
})
module.exports = router;
Can you try like this ? By removing users statement from routes. Since you already defined it in app.use('/users', userRoute);, all routes defined in users.route.js will start with users by default.
let mongoose = require('mongoose'),
express = require('express'),
router = express.Router();
let userSchema = require('../models/User');
// CREATE/POST User
router.route('/').post((req, res, next) => {
userSchema.create(req.body, (error, data) => {
if (error) {
return next(error)
} else {
console.log(data)
res.json(data)
}
})
});
router.route('/').get((req, res) => {
userSchema.find((error, data) => {
if (error) {
return next(error);
} else {
res.json(data);
}
})
})
router.route('/:id').get((req, res) => {
userSchema.findById(req.params.id, (error, data) => {
if (error) {
return next(error);
} else {
res.json(data);
}
})
})
I'm using the MERN stack to build an application for the first time.
In order to log HTTP requests I use "morgan".
I managed to send data to mongodb which seems to be working fine. The problem is that my post request is not coming through. It says "pending" for 4 minutes, then fails.
Here's what I think is the relevant part of my code:
"server.js":
const express = require("express");
const mongoose = require("mongoose");
const morgan = require("morgan");
const path = require("path");
const cors = require("cors");
const app = express();
const PORT = process.env.PORT || 8080;
const routes = require("./routes/api");
const MONGODB_URI =
"...";
mongoose.connect(MONGODB_URI || "mongodb://localhost/app", {
useNewUrlParser: true,
useUnifiedTopology: true
});
mongoose.connection.on("connected", () => {
console.log("Mongoose is connected.");
});
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cors());
app.use(morgan("tiny"));
app.use("/api", routes);
app.listen(PORT, console.log(`Server is starting at ${PORT}`));
Then I've put my routes into another file "api.js":
const express = require("express");
const router = express.Router();
const Lane = require("../models/lanes");
router.get("/", (req, res) => {
Lane.find({})
.then(data => {
res.json(data);
console.log("Get request successful!");
})
.catch(error => {
console.log("Error: ", error);
});
});
router.post("/save", (req, res) => {
const data = req.body;
const newLane = new Lane();
newLane.collection.insertMany(data, err => {
if (err) {
console.log(err);
} else {
console.log("Multiple docs inserted");
}
});
});
module.exports = router;
I'm using axios to send the request. This happens after submitting a form within my application.
reducer function:
const reducer = (state, action) => {
switch (action.type) {
case "add":
axios({
url: "http://localhost:8080/api/save",
method: "POST",
data: [...state, { id: uuid(), title: action.title, tasks: [] }]
})
.then(() => {
console.log("Data has been sent to the server");
})
.catch(() => {
console.log("Internal server error");
});
return [...state, { id: uuid(), title: action.title, tasks: [] }];
The reducer is being used by my context provider component, which looks like this:
export function LanesProvider(props) {
const [lanes, dispatch] = useReducer(reducer, defaultLanes);
return (
<LanesContext.Provider value={lanes}>
<DispatchContext.Provider value={dispatch}>
{props.children}
</DispatchContext.Provider>
</LanesContext.Provider>
);
}
The "add" method inside my reducer is being called when submitting a form inside another component.
Please let me know if I can add anything to my question that would help.
Thank you in advance!
you are not sending any response back to client. Try to modify post method like
router.post("/save", (req, res) => {
const data = req.body;
const newLane = new Lane();
newLane.collection.insertMany(data, err => {
if (err) {
console.log(err);
res.send(err)
} else {
console.log("Multiple docs inserted");
res.send("Multiple docs inserted")
}
});
});
On localhost:5000/posts my data is successfully showing but if I do the same thing in Heroku: https://rest-in-peep.herokuapp.com/posts I get an application error. https://rest-in-peep.herokuapp.com/ works fine and I deployed it through Heroku GIT. I made sure to config my environmental vars in Heroku and added a Procfile but I am still getting this application error. I've been trying all day to figure this out but what I expect to happen is if I type in https://rest-in-peep.herokuapp.com/posts, I will get all the data that is being stored on my MongoDB database.
app.js file
const http = require("http");
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const cors = require("cors");
require("dotenv/config");
const app = express();
const server = http.createServer(app);
//Middlewares
app.use(cors());
app.use(bodyParser.json());
//Import Routes
const postsRoute = require("./routes/posts");
app.use("/posts", postsRoute);
//ROUTES
app.get("/", (req, res) => {
res.send("We are on home");
});
//Connect to DB
mongoose.connect(
process.env.DB_CONNECTION,
{ useNewUrlParser: true },
() => console.log("connected to MongoDB")
);
//How do we start listening to the server
server.listen(process.env.PORT || 5000, () => {
console.log("App now running on PORT");
});
routes>
posts.js
const express = require("express");
const Post = require("../models/Posts");
const router = express.Router();
//GETS BACK ALL THE POSTS
router.get("/", async (req, res) => {
try {
const posts = await Post.find();
res.json(posts);
} catch (err) {
res.json({ message: err });
}
});
//SUBMITS A POST
router.post("/", async (req, res) => {
console.log(req);
const post = new Post({
quote: req.body.quote
});
try {
const savedPost = await post.save();
res.json(savedPost);
} catch (err) {
res.json({ message: err });
}
});
//SPECIFIC POST
router.get("/:postId", async (req, res) => {
try {
const post = await Post.findById(req.params.postId);
res.json(post);
} catch (err) {
res.json({ message: err });
}
});
//Delete Post
router.delete("/:postId", async (req, res) => {
try {
const removedPost = await Post.remove({ _id: req.params.postId });
res.json(removedPost);
} catch (err) {
res.json({ message: err });
}
});
//Update a post
router.patch("/:postId", async (req, res) => {
try {
const updatedPost = await Post.updateOne(
{ _id: req.params.postId },
{
$set: { quote: req.body.quote }
}
);
res.json(updatedPost);
} catch (err) {
res.json({ message: err });
}
});
module.exports = router;
gitignore
/node_modules
models>Posts.js
const mongoose = require("mongoose");
const PostSchema = mongoose.Schema({
quote: {
type: String,
required: true
}
});
module.exports = mongoose.model("Posts", PostSchema);
I'm not sure why it's saying the object is empty. This is my testing block of code.
describe("POST /users", () => {
let body = {
name: "testing",
email: "testing#testing.com",
password: 123456
};
it("Creates a new user", done => {
request(app)
.post("/register")
.send(body)
.end((err, res) => {
if (err) return done(err);
expect(res.body).to.be.equal("testing");
done();
});
});
});
Is there something I'm missing for the test to recognize the information being passed in? As in the payload since I thought that is what .send(payload) was for.
Thanks for the clarity.
** Update Controller and more information **
// Testing
let request = require("supertest");
let expect = require("chai").expect;
let app = require("../../server/server");
describe("GET /test", function() {
it("Returns a json for testing", done => {
request(app)
.get("/test")
.end((err, res) => {
done();
});
});
});
describe("POST /users", () => {
let body = {
name: "testing",
email: "testing#testing.com",
password: 123456
};
it("Creates a new user", done => {
request(app)
.post("/register")
.send(body)
.expect(res => {
expect(res.body).to.be.equal("testing");
})
.end(done);
});
});
// User routes
const express = require("express");
const router = express.Router();
// Load User Model
const User = require("../../models/User");
// #route GET api/users/test
// #desc Tests user route
// #access Public
router.get("/test", (req, res) => res.json({ msg: "Users Works" }));
router.post("/register", (req, res) => {
User.findOne({ email: req.body.email }).then(user => {
if (user) {
res.status(409).json({ msg: "User exist" });
} else {
const newUser = new User({
name: req.body.name,
email: req.body.email,
password: req.body.password
});
newUser
.save()
.then(user => res.status(200).send(user))
.catch(err => console.log(err));
}
});
});
module.exports = router;
// Server
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const app = express();
const users = require("./routes/api/users");
// Body Parser Middleware
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// DB Config
const db = require("../config/keys").mongoURI;
// Connect to MongoDB Atlas
mongoose.connect(
db,
{ useNewUrlParser: true },
(err, client) => {
if (err) {
console.log("Error occurred while connecting to MongoDB Atlas...\n", err);
}
console.log("Connected...");
}
);
// Routes
app.use("/api/users", users);
const port = process.env.PORT || 5000;
let server = app.listen(port, () =>
console.log(`Server running on port ${port}`)
);
module.exports = server;
I'm trying to create my first MongoDB app with Express & Angular & Azure Cosmos DB.
Here is my js files:
hero.model.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const heroSchema = new Schema({
id: {
type: Number,
required: true,
unique: true
},
name: String
}, {
collection: 'Heroes'
})
const Hero = mongoose.model('Hero', heroSchema);
module.exports = Hero;
mongo.js
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
const env = require('./env/environment');
const mongoUri =
mongodb:`${env.accountName}:${env.key}#${env.accountName}
.documents.azure.com:10255/?ssl=true`
function connect() {
mongoose.set('debug', true);
return mongoose.connect(mongoUri)
}
module.exports = {
connect,
mongoose
};
index.js
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const routes = require('./routes');
const root = './';
const port = process.env.PORT || '3000';
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(root, 'docs')));
app.use('/api', routes);
app.get('*', (req, res) => {
res.sendFile('docs/index.html', {root});
});
route.js
const express = require('express');
const router = express.Router();
const heroService = require('./hero.service');
router.get('/heroes', (req, res) => {
heroService.getHeroes(req, res);
});
router.post('/hero', (req, res) => {
heroService.postHero(req, res);
});
router.put('/hero/:id', (req, res) => {
heroService.putHero(req, res);
});
router.delete('/hero/:id', (req, res) => {
heroService.deleteHero(req, res);
});
module.exports = router;
app.listen(port, () => console.log(`API running on
localhost:${port}`));
hero.service.js
const Hero = require('./hero.model');
require('./mongo').connect();
function getHeroes(req, res) {
const docquery = Hero.find({});
docquery
.exec()
.then(heroes => {
res.status(200).json(heroes);
})
.catch(error => {
res.status(500).send(error);
return;
});
}
function postHero(req, res) {
const originalHero = {
id: req.body.id,
name: req.body.name
};
const hero = new Hero(originalHero);
hero.save(error => {
if (checkServerError(res, error)) return;
res.status(201).json(hero);
console.log('Hero created successfully!');
});
}
function checkServerError(res, error) {
if (error) {
res.status(500).send(error);
return error;
}
}
function putHero(req, res) {
const originalHero = {
id: parseInt(req.params.id, 10),
name: req.body.name
};
Hero.findOne({
id: originalHero.id
}, (error, hero) => {
if (checkServerError(res, error)) return;
if (!checkFound(res, hero)) return;
hero.name = originalHero.name;
hero.save(error => {
if (checkServerError(res, error)) return;
res.status(200).json(hero);
console.log('Hero updated successfully!');
});
});
}
function deleteHero(req, res) {
const id = parseInt(req.params.id, 10);
Hero.findOneAndRemove({
id: id
})
.then(hero => {
if (!checkFound(res, hero)) return;
res.status(200).json(hero);
console.log('Hero deleted successfully!');
})
.catch(error => {
if (checkServerError(res, error)) return;
});
}
function checkFound(res, hero) {
if (!hero) {
res.status(404).send('Hero not found.');
return;
}
return hero;
}
module.exports = {
getHeroes,
postHero,
putHero,
deleteHero
};
It only works when I POST a new hero for the first time and a second time gives me an error:
E11000 duplicate key error collection: admin.Heroes Failed _id or unique key constraint.
Please help!!
Thanks.
I know it's been a while but I've encountered the same problem. The solution is avoid using the field name id, rename it to UID or something. Once you done that you have to remove the entire collection and restart.
If you are following the Microsoft CosmosDB Angular tutorial, you can clone the repo below and test it on your local.
https://github.com/Azure-Samples/angular-cosmosdb
If you are using a newer version of mongoose you have to upgrade the connection string below.
//useMongoClient: true
useNewUrlParser: true