How to unselect a particular document in mongoose - express

I have access to userId and I want to get result without document of that particular user. How can I do this in mongoose?
async peopleyoumayknow(req, res) {
const {id} = req.params
const response = await userModel.find({}).sort({creation_date:-1}).limit(12)
return res.send(response)
}

Update your code to
async peopleyoumayknow(req, res){
const {id} = req.params
const response = await userModel.find({ _id: {"$ne": id}}).sort({creation_date:-1}).limit(12);
return res.send(response)
}

Related

how to pass req.params in a {mergeparams} for a post request express

I am trying to make a post request in a nested route but i keep getting 404 on postman.
app.js to handle my routes
app.use("/channel", controllers.channelController);
app.use("/channelentry", controllers.channelEntryController);
channelcontroller
const Express = require('express');
const router = Express.Router();
const channelEntry = require('./channelentrycontroller')
router.use('/:channelId', channelEntry)
channelEntryController
const Express = require('express');
const channelEntry = Express.Router({mergeParams: true});
channelEntry.get("/", async (req, res) => {
const channelId = req.params.channelId
try {
const messages = await models.ChannelEntryModel.findAll({
include: [{
model: models.ChannelModel,
where: { channelId: channelId }
}],
});
res.status(200).json({messages})
} catch (err) {
res.status(500).json({error: err})
}
});
channelEntry.post("/create", validateJWT, async (req, res) => {
const {entry} = req.body.channelentry
const channelId = req.params.channelId
const channelMessage = {
entry,
userId: req.user.userId,
channelId: channelId
}
try {
const currentChannelId = await models.ChannelModel.findOne({
where: {
channelId: channelId
}
})
const newChannel = await models.ChannelEntryModel.create(channelMessage, currentChannelId);
res.status(200).json(newChannel)
} catch (err) {
console.log(err)
res.status(500).json({error: err})
}
})
my get request works but sends an empty array because i have no entrys.
I ended up answering my own question.
I commented out:
app.use("/channelentry", controllers.channelEntryController);
I guess it was conflicting with my other route.

display data on page when user is auth, express , jwt, cookie-parser

I have simple application where user can register and login in his acc, now i want display user login on page, how i can get data from db about user that authinticated now
i also use mongodb and moongose as database
this register sistem
router.post('/register',async (req,res)=>{
const {login,mail,password} = req.body
bcrypt.hash(password, 10).then((hash) =>{
User({login:login,password:hash,mail:mail}).save()
})
res.redirect('/login')
})
this is login sistem
router.post('/',async (req,res)=>{
const {mail, password } = req.body
const user = req.body
console.log(user)
const isUserExist = await User.findOne({mail:mail})
const UserPwdCorrect = isUserExist.password
if(!isUserExist){
console.log('Логин гавно')
} else{
bcrypt.compare(password,UserPwdCorrect).then((match)=>{
if(!match){
console.log("Пароль говно")
} else{
const accessToken = createToken(user)
res.cookie("token",accessToken,{
maxAge:60*60*24*30*1000
})
res.redirect('/')
}
})
}
})
and this is what i did in jwt.js file
const {sign,verify} = require("jsonwebtoken")
const createToken = (user) =>{
const accessToken = sign({login: user.login, isAdmin:user.idAdmin,id:user.id},"jwt-secret")
return accessToken
}
const validateToken = (req,res,next) =>{
const accessToken = req.cookies["token"]
console.log(accessToken)
if(accessToken){
try {
const validtoken = verify(accessToken,"jwt-secret")
if(validtoken){
req.authenticated = true
return next()
} else{
return next()
}
} catch(err){
console.log(err)
}
}
}
Here's one solution:
Pass in userID in the JWT token. When the user clicks on the profile page, send a POST request to an endpoint that accepts the token (in a header). The backend verifies the token, extracts the userID, makes the DB call, and finally returns the response.
An advantage to this approach is that your profile route is authenticated (i.e, the route is secure).

Express router's mock post handler doesn't work as expected

I have a documents router which has router.post('/mine', [auth, uploadFile], async (req, res) => { ... }) route handler. The actual implementation of this route handler is below.
documents.js router
const createError = require('./../helpers/createError');
const auth = require('./../middlewares/auth');
const uploadFile = require('./../middlewares/uploadFile');
const express = require('express');
const router = express.Router();
router.post('/mine', [auth, uploadFile], async (req, res) => {
try {
let user = await User.findById(req.user._id);
let leftDiskSpace = await user.leftDiskSpace();
if(leftDiskSpace < 0) {
await accessAndRemoveFile(req.file.path);
res.status(403).send(createError('Your plan\'s disk space is exceeded.', 403));
} else {
let document = new Document({
filename: req.file.filename,
path: `/uploads/${req.user.username}/${req.file.filename}`,
size: req.file.size
});
document = await document.save();
user.documents.push(document._id);
user = await user.save();
res.send(document);
}
} catch(ex) {
res.status(500).send(createError(ex.message, 500));
}
});
module.exports = router;
I'm currently writing integration tests using Jest and Supertest. My current documents.test.js test file is below:
documents.test.js test file
const request = require('supertest');
const { Document } = require('../../../models/document');
const { User } = require('../../../models/user');
const fs = require('fs');
const path = require('path');
let server;
describe('/api/documents', () => {
beforeEach(() => { server = require('../../../bin/www'); });
afterEach(async () => {
let pathToTestFolder = path.join(process.cwd(), config.get('diskStorage.destination'), 'user');
// Remove test uploads folder for next tests
await fs.promises.access(pathToTestFolder)
.then(() => fs.promises.rm(pathToTestFolder, { recursive: true }))
.catch((err) => { return; });
// Remove all users and documents written in test database
await User.deleteMany({});
await Document.deleteMany({});
server.close();
});
describe('POST /mine', () => {
it('should call user.leftDiskSpace method once', async () => {
let user = new User({
username: 'user',
password: '1234'
});
user = await user.save();
let token = user.generateAuthToken();
let file = path.join(process.cwd(), 'tests', 'integration', 'files', 'test.json');
let documentsRouter = require('../../../routes/documents');
let errorToThrow = new Error('An error occured...');
user.leftDiskSpace = jest.fn().mockRejectedValue(errorToThrow);
let mockReq = { user: user };
let mockRes = {};
documentsRouter.post = jest.fn();
documentsRouter.post.mockImplementation((path, callback) => {
if(path === '/mine') {
console.warn('called');
callback(mockReq, mockRes);
}
});
const res = await request(server)
.post('/api/documents/mine')
.set('x-auth-token', token)
.attach('document', file);
expect(documentsRouter.post).toHaveBeenCalled();
expect(user.leftDiskSpace).toHaveBeenCalled();
});
});
});
I create mock post router handler for documents.js router. As you can see from mockImplementation for this route handler, it checks if the path is equal to '/mine' (which is my supertest endpoint), then calls console.warn('called'); and callback. When I run this test file, I can not see any yellow warning message with body 'called'. And also when POST request endpoint /api/documents/mine the server doesn't trigger my mock function documentsRouter.post. It has never been called. So I think the server's documents router is not getting replaced with my mock post route handler. It still uses original post route handler to respond my POST request. What should I do to test if my mock documentsRouter.post function have been called?
Note that my User model has a custom method for checking left disk space of user. I also tried to mock that mongoose custom method but It also doesn't work.

I am tring to make Static Model.findByCredentials. But it is not working for mongoose, Express login system?

userSchema.statics.findByCredentials = async (email, password) =>{
const user =await User.findOne({ email })
if(!user){
throw new Error("Unable to Login!")
}
const isMatch = await bcrypt.compare(password, user.password)
if (!isMatch){
throw new Error("Invalid to Login!!")
}
return user
}
const User = new mongoose.model("User",userSchema)
module.exports = User
In users i have set the routes properly too:
router.post("/users/login", async (req,res) => {
try{
const user = await User.findByCredentials(req.body.email, req.body.password)
res.send(user)
}
catch(err){
res.status(400).send()
}
})
But i get 400 Bad request error. The route is catching the error.
findByCredentials is not working?
What is my mistake??

Converting Url parameters to object id

How can Id gotten from request parameter in express be converted to object id for Mongoose
Let's say for instance
app("path/get_user_b
yid/:id6888",(req,
res)=>.{
//code to convert I'd
back to object...
}
you can call findById function to get a specific user as bellow
const mongoose = require('mongoose');
connst Schema = mongoose.Schema;
const User = new Schema({
name: String,
...
// other data
});
app.get('path/get_user_b yid/:id', (req, res) => {
cosnt id = req.params.id;
User.findById(id, function (err, user) {
if (err) {
return res.status(500);
}
return res.status(200).json(user);
});
});