Hey again,
So I have a public facing server that Payload is sitting on, so the API is accessible from anywhere. This I have no problem with, however, one of my hooks sends out an email to an email list collection. I definitely don't want to have my users email addresses accessible publicly, however, I do want them to be able to be created and deleted publicly.
Currently I have some hacky code that uses a fetch request from within the payload hook to pull down the email list and send emails out to it, but this is only possible because that collection can be read publicly.
How do I go about accessing Collection Docs internally?
Here is my current (insecure) implementation:
const emailSubscribers = async ({doc}) => {
if(doc.notify === true){
const responseEmail = await fetch(HOST+`/api/emaillist`)
const emails = await responseEmail.json()
const responseImage = await fetch(HOST+`/api/media/${doc.featureImage}`)
const image = await responseImage.json()
let imageBuffer = await axios.get(image.sizes.feature.url, {responseType: 'arraybuffer'})
let raw = Buffer.from(imageBuffer.data).toString('base64')
let base64Image = `data:${imageBuffer.headers["content-type"]};base64,${raw}`
// console.log(base64Image)
for(const emailObj of emails.docs) {
const htmlToSend = HtmlTemplate({
title: doc.title,
subtitle: doc.subtitle,
imageLink: base64Image,
unsubscribeLink: HOST+"/unsubscribe/"+emailObj.id,
postLink: WEBSITE+`/posts/${doc.slug}`
})
payload.sendEmail({
from: "User <User@email.com>",
to: emailObj.email,
subject: "New Article!",
html: htmlToSend
})
}
console.log("Subscribers Notified!")
}
};
Hey @peniswafflexd — this is super easily solved actually via a few options.
In any case, and as you probably know already, you should restrict read
access control to any collections that should not be publicly readable. However, once access is restricted, you can:
read
access, and then using the returned token to authenticate in your fetchpayload.find({ /* options here */ })
. This is how you should typically access Payload operations from hooks, because it avoids having to use an HTTP layer and just stays right on your server. Definitely what we would do.Do any of these options work? Have you used the Local API yet?
Wow that was solved super easily!
Sorry my bad, I assumed the local API was something completely different but that solved it straight away.
All I needed to do was swap:
const responseEmail = await fetch(HOST+`/api/emaillist`)
const emails = await responseEmail.json()
with
const emails = await payload.find({
collection: 'emaillist',
});
and it worked straight away!
I just turned read access off and it works fine now
Hell yeah