Find one user on moongose - node.js

I have the following problem to solve: I have multiple users in a database (mongoDB). Pass the following, in a specific url, for example: "my-page/users/here-goes-the-name-of-the-user". When displaying the username in the url, I convert it to lowercase and replace the spaces with hyphens: Husdady Mena ===> /husdady-mena.
In the database, the user names are as shown before converting the name to lowercase, eg: Husdady Mena, Donald Trump, Will Smith, etc.
I need to somehow filter a user, which is in the url as /husdady-mena with the database user: Husdady Mena, in order to obtain his information, how could that filter be done in mongoose?
A clear example with js:
const users = [{ name: 'Husdady Mena' }, {name:'Donald Trump'}, {name:'Will Smith'}, {name:'Dubá Solis'}]
const username = "dubá-solis"
const url = `my-page.com/users/${username}`
const userToFilter = url.substring(url.lastIndexOf("/") + 1)
const userFound = users.find(({ name }) => {
const usernameToLowerCase = name.toLowerCase().replace(/\s/gim, "-")
return userToFilter === usernameToLowerCase
})
console.log(userFound)
If the example is not clear to you: I make a request from the frontend to the backend to obtain a specific user, I need to obtain the user by name, it is not necessary to obtain it by id. In the url something like: my-page/users/dubá-solis is painted, I get the name of the user, which is: dubá-solis. in the backend is something like:
// Librarys
const { Router } = require('express')
const router = Router()
// Models
const User = require('#models/users/User')
router.get(
'/users/:username',
function(req, res) {
try {
// req.params.username === "dubá-solis"
const userFound = await User.findOne({ name: req.params.username })
// In database, the username is Dubá Solis, that's why it returns me null
return res.status(200).json(userFound)
} catch(err) {
console.log('[UserFound.err]', err)
}
}
)
module.exports = router

Why not just convert the username and pass that to the query function? Something like:
const convertUsername = username => {
const nameParts = username.split('-');
return nameParts.map(n => n.slice(0, 1).toUpperCase() + n.slice(1))
.join(' ');
};
console.log(convertUsername('dubá-Solis'));
console.log(convertUsername('joan-of-arc'));
Then, just do User.findOne({ name: convertUsername(req.params.username) })

Related

I need to make a request using Prisma that brings selected products by IDs

I have a backend function that returns a request based on an id.
I need it to return me based on an array of ids
If I pass only one ID it works fine, but if I pass more than one, it gives error....
Can someone help?
Thanks
Backend function:
` import prisma from '../../../../libs/prisma'
export default async function handle(req, res) {
const { ids } = req.query
const idsArray = ids.split(',')
const products = await prisma.product.findMany({
where: {
id: {
in: Number(idsArray),
},
},
})
res.json(products)
}`
And Frontend function that passes the parameters on the front is:
const { selectProducts, setSelectProducts } = useContext(ProductContext)
const [productsInfo, setProductsInfo] = useState([])
useEffect(() => {
const uniqIds = [...new Set(selectProducts)]
fetch('/api/products/getAllSelectedProducts?ids=' + uniqIds.join(',')).then((response) => response.json()).then((json) => setProductsInfo(json))
}, [selectProducts])

Cloud Functions Firestore get key value for increment

I'm trying to get the updated number for a Member Number from a document using Cloud Functions when an admin creates a user.
What should happen is when an Admin creates a user in their dashboard, the user is added to firebase, then the member number updates, and is applied to newMemNum, then updated in the user document.
My Code:
const memNumInc = admin.firestore.FieldValue.increment(1);
const memCounter = admin.firestore().collection(`mem_num`).doc(`a1lDbrsoXjfKeosEkDtw`);
memCounter.update({number: memNumInc}).then(() =>
memCounter.get()
.then((snap) => {
const id = snap.id;
const data = snap.data()
newMemNum = data['number']
console.log('New Member Number: ' + newMemNum);
return {id, ...data};
})
);
The increment goes ok (i.e. number goes up by 1 which is expected), but the next part of the code doesn't run and doesn't throw an error.
Also, the next part of the code that updates the user document doesn't fire at all, and no errors.
Entire Code:
// Create User Document onCreate
const createProfile = (userRecord) => {
const uid = userRecord.uid;
const docId = userRecord.uid;
const fullName = userRecord.displayName || 'New User';
const memStatus = 'Unfinancial';
const isAdmin = false;
const isNew = true;
const email = userRecord.email;
const photoUrl = userRecord.photoUrl;
const phone = '0444 123 456';
const createdAt = admin.firestore.FieldValue.serverTimestamp();
const memNumInc = admin.firestore.FieldValue.increment(1);
const memCounter = admin.firestore().collection(`mem_num`).doc(`a1lDbrsoXjfKeosEkDtw`);
memCounter.update({number: memNumInc}).then(() =>
memCounter.get()
.then((snap) => {
const id = snap.id;
const data = snap.data()
newMemNum = data['number']
console.log('New Member Number: ' + newMemNum);
return {id, ...data};
})
);
return afs
.collection(`users`)
.doc(docId)
.set({
uid: uid,
docId: docId,
fullName: fullName,
joined: createdAt,
memNum: newMemNum,
memStatus: memStatus,
isAdmin: isAdmin,
isNew: isNew,
email: email,
photoUrl: photoUrl,
phone: phone,
addedOn: createdAt,
updatedOn: createdAt
})
.then(() => console.log('User Creaeted Successfuly: ' + uid))
.catch((e) => console.log('User Creation Error: ' + e.message));
}
exports.authOnCreate = functions.auth.user().onCreate(createProfile);
If I remove the memCounter code, the rest executes no problem.
You have another return statement that most likely runs before the promise returned by get() is resolved. Try refactoring the code using async-await syntax as shown below:
const createProfile = async (userRecord) => {
// const vars ....
const memNumInc = admin.firestore.FieldValue.increment(1);
const memCounter = admin.firestore().collection(`mem_num`).doc(`a1lDbrsoXjfKeosEkDtw`);
// Update documents
await memCounter.update({
number: memNumInc
})
// Get update document data
const snap = await memCounter.get()
const id = snap.id;
const data = snap.data()
newMemNum = data['number']
console.log('New Member Number: ' + newMemNum);
return afs
.collection(`users`)
.doc(docId)
.set({ ... })
}
However, if multiple users are created simultaneously, there's a chance that they'll get the same newMemNum so a transaction might be useful as well.
Firestore also introduced a new COUNT() function that can be used to get total number of documents in a collection instead of incrementing the count every time.

Is there any way to ignore backslashes and forward slashes in link route?

I am making a user Authentication system and it sends users a confirmation email when user registers, the problem I'm facing is that sometimes link contains / and \ .due to this any text after the / was considered as new route. Is there any way to ignore these slashes. btw I'm using hashing to generate the link.
The link is generated by this piece of code.
const hashedEmail = await bcrypt.hash(email,10);
console.log(await bcrypt.compare(email,hashedEmail))
const mailOptions = {
from: 'someone#gmail.com',
to: email,
subject: 'Confirm your email',
text : `Thanks for registering! Please click on the link to confirm your email:
http://localhost:3500/confirm/${hashedEmail}`
}
confirmation Route
const bcrypt = require('bcrypt');
const fsPromises = require('fs').promises;
const path = require('path');
// user data:
const userData = {
users: require('../model/users.json'),
setUsersData : function(data) {this.users = data}
}
async function confirmationRoute(fastify,options,done){
fastify.get('/confirm/:id',async(req,res) => {
const HashedId = req.params.id;
let foundUser;
for (let i = 0; i < userData.users.length; i++) {
if (await bcrypt.compare(userData.users[i].email,HashedId)){
foundUser = userData.users[i];
}
}
if(foundUser){
// change isverified to true
foundUser.isVerified = true;
// write the new user data to the file
userData.setUsersData([...userData.users.filter(user => user.email !== foundUser.email),foundUser]);
await fsPromises.writeFile(path.join(__dirname,'..','model','users.json'),
JSON.stringify(userData.users)
);
res.send({"message":"Account Verified"})
}
else{
res.send({"message":"Invalid Link"})
}
})
done()
}
module.exports = confirmationRoute;
Example Link is : http://localhost:3500/confirm/$2b$10$bWUrZ6d0dQuZ8.e/Hqd..OEIaFN2By3nVE6x6H2sHCyLlA/nTriKO
You need to encode the parameter and decode it before processing it:
const param = encodeURIComponent('hello/world?')
console.log(param)
const data = decodeURIComponent(param)
console.log(data)

Pass variable into collection(collectionName).doc(docName)

I am creating a cloud firestore function. The last step I need for now is using the userId to retrieve a document.
Here I get the userId
const userId = snap.data().userId; <<< THIS WORKS
console.log('A new transaction has been added');
Here I want insert the value from userId to retrieve the correct document.
const deviceDoc = db.collection('device').doc(**userId**); <<< THIS IS THE PROBLEM
const deviceData = await deviceDoc.get();
const deviceToken = deviceData.data().token;
I don't know how to use the variable, userId, to insert the value into the .doc(userId) to get the data.
If userId = 12345 I want the line to look like this:
const deviceDoc = db.collection('device').doc('12345');
I have tried .doc('userId'), .doc('${userId}'), as well as other things. None of these work.
How do I do this?
As Puf has responded, you can simply use doc(userId). The rest of your code looks fine, so maybe the document you are getting doesn't exist. Try the following:
const deviceRef = db.collection('device').doc(userId);
// you can shorten this to >> const deviceRef = db.doc(`device/${userId}`);
try {
const deviceDoc = await deviceRef.get();
if (!deviceDoc.exists) {
console.log(`The document for user ${userID} does not exist`);
} else {
const {token} = deviceDoc.data();
console.log('The token is:', token);
}
}
catch (err) {
console.error(err);
}

It is not giving userid in url when i visit this route

router.get("/dashboard/profile/:userid", auth, async (req, res) => {
try {
const userid = req.params.user.id;
// request.user is getting fetched from Middleware after token authentication
const user = await User.findById(userid);
res.json(user);
} catch (e) {
res.send({ message: "Error in Fetching user" });
}
});
module.exports = router
this is my get route i tried to get params.id from user but it is not working
replace this
const userid = req.params.user.id
with
const userid = req.params.userid
userid is a single key. But you separated with user.id . so use
const userid = req.params.userid;
instead of
const userid = req.params.user.id;
its not working only getting localhost:3000/dashboard/profile ?
You are missing the userid value on your path.
Please check it there is three segment.
dashboard/profile/:userid
1 2 3
But your path are (problem)
localhost:3000/dashboard/profile
1 2
please don't consider the host name and port. calculate after /
solution
localhost:3000/dashboard/profile/YourUserID
1 2 3(//add your userid here)

Resources