i'm newbie with MEAN stack and i have problem when updating data with put Method, i have tested using postman and it works fine, but when i use it on angular its not working. nothing error appear, this what i got in console after updating data
[is give success update][1] but nothing change on data that i updated. i don't have problem with create and delete method, just update method that had problem
here's my code
update.service
updateData(id, data): Observable<any>{
let url = `${this.baseUri}/update/${id}`;
return this.http.put(url,data, { headers : this.headers }).pipe(
catchError(this.errorManagement)
)}
update.component
OnSubmit(id){
let record = this.updateForm.value
if(!record){
this.notif.showError('can\'t do update data','Update data Error')
return false;
}else{
return this.motorService.updateData(id, record).subscribe(res=>{
console.log(record)
},(error) => {
console.log(error)
});
}}}
update route
listDataRoute.route('/update/:id').put((req,res,next)=>{
listData.findByIdAndUpdate(req.params.id,{
$set : req.body
},{new: true, useFindAndModify: false},(error, data)=>{
if (data.n > 0) {
res.status(200).json({
message: 'profile updated'
});
} else {
res.status(401).json({
message: 'not authorized'
});
}
})
.catch(error => {
res.status(500).json({
message: 'updating profile failed'
});
})
})
any idea what i do wrong ? i'm already stuck like 5 hours with this error, thank you
[1]: https://i.stack.imgur.com/ryR8g.png
update : i got error 401 after adding some code in "update route", still don't know how to solve this error
id like to share my way of updating data with the mean stack. its a lil different from your code but it works and is tested with jest. id like to share my example with updating a userprofile
i create a userModel in my backend user.js
// user.js
const mongoose = require("mongoose");
const uniqueValidator = require("mongoose-unique-validator");
mongoose.set('useCreateIndex', true);
const userSchema = mongoose.Schema({
id: String,
email: { type: String, unique: true },
username: { type: String, unique: true },
password: { type: String, required: true },
currentLocation: String,
age: String,
});
userSchema.plugin(uniqueValidator);
module.exports = mongoose.model('User', userSchema);
then i write the update method in my profileController.js
// profileController.js
exports.update = (req, res, next) => {
const user = new User({
_id: req.body.id,
email: req.body.email,
username: req.body.username,
currentLocation: req.body.currentLocation,
age: req.body.age,
});
User.updateOne({ _id: req.params.id }, user).then(result => {
if (result.n > 0) {
res.status(200).json({
message: 'profile updated'
});
} else {
res.status(401).json({
message: 'not authorized'
});
}
})
.catch(error => {
res.status(500).json({
message: 'updating profile failed'
});
});
}
in my profilerService.ts (frontend) i also define my userclass with the same properties as the user.js model in my backend
// profile.service.ts
export class User {
id: string;
email: string;
username: string;
password: string;
currentLocation: string;
age: string;
constructor() {
this.id = '';
this.email = '';
this.username = '';
this.password = '';
this.currentLocation = '';
this.age = '';
}
}
i also add the update service call into my service file
// profile.service.ts
updateProfile(user: User, userId: string) {
return this.http.put(environment.backendUrl + '/api/user/' + userId, user);
}
then i can call the service function from my component where i want to update my user
// profile-page.component.ts
updateProfile(user: User) {
this.profileService.updateProfile(user, user.id).subscribe(response => {
console.log('update successfull');
});
}
i hope my code snippets are able to help you! let me know if anything still needs some clarification. sry if this isnt the most perfect answer as this is one of my first answers on SO :)
401 means Authentication error.
Is post working?
Related
i want to display last login time of user in table column after they logged in. i tried with some code in backend with nodejs and mongoose but sure it is not the right way. Can anyone help me how to handle it from backend and FE as well?
Here is Schema of user:
const userSchema = new Schema(
{
name: { type: String },
email: { type: String, unique: true},
password: { type: String },
status: {type: String, enum:["Active", "Blocked"], default:"Active"},
token: { type: String },
lastLogin: { type: Date, default: Date.now()},
},
{ timestamps: true }
);
Route:
userRouter.post("/login", async (req, res, next) => {
try {
const { email, password } = req.body;
if (!(email && password)) res.status(204).send({ msg: "All fields are required!" });
const user = await UsersModel.findOne({ email });
console.log(user);
if (user && (await bcrypt.compare(password, user.password))) {
const accessToken = await JWTAuthenticate(user);
user.token = accessToken;
user.lastLogin = Date.now()
res.status(200).send(user);
} else {
res.status(404).send({ msg: "User with this email not found!" });
}
UsersModel.findOneAndUpdate({lastLogin: Date.now()}, (err, data) => {
if(err) console.log(err);
else console.log("Successfully updated the lastLogin", data);
})
} catch (error) {
next(error);
}
});
You just have to call await user.save() after setting lastLogin (and remove findOneAndUpdate call)
or
actually query for the user in your findOneAndUpdate call. Currently you are querying for a 'lastLogin' field with the value now() which will never match. Adjust this call as following:
UsersModel.findByIdAndUpdate(user._id, {lastLogin: Date.now()}, (err, data) => {
if(err) console.log(err);
else console.log("Successfully updated the lastLogin", data);
})
Just a hint: JWTs are used for storing the session state on client side. You don't need to actually store these Tokens in your database. You just have to validate it on incoming request.
when I use this code to try and update the user it appears as a server error. Im using JWT and mongodb but am unsure if im pulling the token or the id to update the users information. Below my controller code is attached and my schema.
const updateUser = async (req, res) => {
try {
const user = await User.findByIdAndUpdate(req.user.id)
if(!user) return res.status(400).send({ error: 'User not found'})
Object.assign(user, req.body);
user.save()
res.send({ data: user})
} catch (error) {
res.status(500).send({error: 'Server Error'})
}
}
const mongoose = require('mongoose');
let userSchema = new mongoose.Schema({
name: { type: String, required: true},
email: { type: String, required: true, unique: true},
password: { type: String, required: true},
date: { type: Date, default: Date.now}
})
module.exports = mongoose.model('user', userSchema)
Updated update function but i appear to have an error
const updateUser = async (req, res) => {
try {
const updatedUser = await User.findByIdAndUpdate(req.params.id,req.body)
if(!updatedUser) return res.status(400).send('User cannot be updated!')
res.json(updatedUser)
} catch (error) {
res.status(500).send({error: 'Server Error'})
}
}
Try this :
//update user by id
exports.updateUser = async (req, res) => {
try {
const updatedUser = await
<--req.params.id is the user.id and req.body contains the requested fields to update -->
User.findByIdAndUpdate(req.params.id,req.body)
res.json(updatedUser);
}
catch (err) {
console.log(err);
res.status(500).json({ message: 'Internal server error' });
}
}
Working on a personal project, one of the functions of the project is to update the user status on what event they are participating.
i wanted to submit a value using a button
<form action="/users/fooddrivebanner" method="POST"><button name="fooddrive" type="submit" value="fooddrive" id="fooddrive">Participate</button></form>
then pass the value to my route and save it inside my database
router.post('/fooddrivebanner', (req,res)=>{
const { fooddrive } = req.body;
const _id = ObjectId(req.session.passport.user._id);
User.findOne({ _id: _id }).then((user)=>{
if (!user) {
req.flash("error_msg", "user not found");
res.redirect("/fooddrivebanner");
}
if (typeof eventparticpating !== "undefined") {
user.eventparticpating = 'fooddrive';
}
user.save(function (err, resolve) {
if(err)
console.log('db error', err)
// saved!
});
})
.catch((err) => console.log(err));
Here is the User model
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
},
eventparticpating: {
type: String,
default: 'None At The Moment'
}
});
const User = mongoose.model('User', UserSchema);
module.exports = User;
It showed a console error
TypeError: Cannot set property 'eventparticpating' of null
UPDATE
Edit 1:
I followed Mr Gambino instructions, error Gone yet cannot update the database, how would i be able to adjust and find my user?
Instead of saving within the findOne function,you can do this:
router.post('/fooddrivebanner', async (req,res) => {
const { fooddrive } = req.body;
const _id = ObjectId(req.session.passport.user._id);
await User.findOne({ _id: _id }, (error, user) => {
if (error) {
req.flash("error_msg", "user not found");
res.redirect("/fooddrivebanner");
}
}).updateOne({ eventparticpating: "foodrive" });
});
I hope that answers your question
I have one model is user in that model I was added email, username, password and name , when I have insert this data using node JS with the help of rest API, so that condition all 4 records are stored in one table
but I want email and name is stored in registration table and username and password stored in login table ,when I put login request using postman it with username name and password credentials it gives the successful response.
I am new to Node
My controller is
exports.user_signup = (req, res, next) => {
User.find({ username: req.body.username })
.exec()
.then(user => {
if (user.length >= 1) {
return res.status(409).json({
message: "Mail exists"
});
} else {
bcrypt.hash(req.body.password, 10, (err, hash) => {
if (err) {
return res.status(500).json({
error: err
});
} else {
const user = new User({
_id: new mongoose.Types.ObjectId(),
username: req.body.username,
password: hash,
email: req.body.email,
contact: req.body.contact,
});
user
.save()
.then(result => {
// console.log(result);
res.status(201).json({
message: "User created"
});
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
}
});
}
});
};
My Postman post method is in JSON form
{
"username":"tene",
"password":"tene",
"email":"tene#gmail.com",
"contact":1234567890
}
You can try this:
import mongoose from 'mongoose'
const { Schema } = mongoose
const userSchema = new Schema(
{
registrationTable : {
email: { type: String, required: true },
mobileNo: { type: String, required: true }
},
loginTable: {
username: { type: String, required: true },
password: { type: String, required: true }
}
},
{ timestamps: true }
)
const UserModel = mongoose.model('User', userSchema)
It will depend on you if you wanna make registration and login table as an object or array, but this will sure help.
required: true will be for, you need that value necessary, if you dont want some value just remove this.
I am trying to update user data in the settings page. Where he/she can change all details like name, last name, birthday and so on. Here is the auth controller:
module.exports = {
async CreateUser(req, res) {
const schema = Joi.object().keys({
username: Joi.string()
.min(4)
.max(10)
.required(),
email: Joi.string()
.email()
.required(),
firstName: Joi.string()
.required(),
lastName: Joi.string()
.required(),
position: Joi.string()
.required(),
password: Joi.string()
.min(5)
.required(),
});
const { error, value } = Joi.validate(req.body, schema);
if (error && error.details) {
return res.status(HttpStatus.BAD_REQUEST).json({ msg: error.details })
}
const userEmail = await User.findOne({
email: Helpers.lowerCase(req.body.email)
});
if (userEmail) {
return res
.status(HttpStatus.CONFLICT)
.json({ message: 'Email already exist' });
}
const userName = await User.findOne({
username: Helpers.firstUpper(req.body.username)
});
if (userName) {
return res
.status(HttpStatus.CONFLICT)
.json({ message: 'Username already exist' });
}
return bcrypt.hash(value.password, 10, (err, hash) => {
if (err) {
return res
.status(HttpStatus.BAD_REQUEST)
.json({ message: 'Error hashing password' });
}
const age = moment().diff(moment([value.byear, value.bmonth - 1, value.bday]), 'years');
const body = {
username: Helpers.firstUpper(value.username),
email: Helpers.lowerCase(value.email),
firstName: value.firstName,
lastName: value.lastName,
position: value.position,
password: hash,
};
User.create(body)
.then(user => {
const token = jwt.sign({ data: user }, dbConfig.secret, {
expiresIn: '5h'
});
res.cookie('auth', token);
res
.status(HttpStatus.CREATED)
.json({ message: 'User created successfully', user, token });
})
.catch(err => {
res
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.json({ message: 'Error occured' });
});
});
},
User model
const userSchema = mongoose.Schema({
username: { type: String },
email: { type: String },
isVerified: { type: Boolean, default: false },
firstName: { type: String },
lastName: { type: String },
position: { type: String },
password: { type: String },
I guess I shoud have a route like this:
router.post('/user/settings', AuthHelper.VerifyToken, user.editUser);
How should it look like editUser controller according to above CreateUser function? I am using Angular in the front-end. But I think it doesn't matter. I assume 90 percent should be the same as CreateUser but what exactly should be changed so the user can update his/her details in settings form and change data in the model?
So you want to update some of user's fields (such as firstName, lastName and etc.), not replacing the whole information. Then you might want to get the current user's data first and then update only those allowed fields.
Please find the sample code below.
/**
* User router
*/
router.put('/user/:userId', AuthHelper.VerifyToken, user.editUser);
// This function will be triggered when Express finds matching route parameter
router.param('userId', function (req, res, next, id) {
User.findOne(id, function (err, user) {
if (err) {
next(err);
} else if (user) {
// When it finds user information, bind that to request object, which will be used in the other middlewares.
req.user = user;
next();
} else {
next(new Error('failed to load user'));
}
});
});
/**
* User controller
*/
exports.editUser = (req, res, next) => {
let { user } = req;
// You pick only allowed fields from submitted body
const allowedFields = { firstName: req.body.firstName, lastName: req.body.lastName, birthday: req.body.birthday };
// Override the current user data with new one
user = Object.assign(user, allowedFields);
user.save((err, savedUser) => {
if (err) {
return next(err);
}
res.json(savedUser.toJSON());
});
};