Securing read operations
Last updated
Was this helpful?
Last updated
Was this helpful?
Was this helpful?
To secure a read operation, you'll want to add a read
rule.
module.exports = {
"default": {
"projects": {
"read": () => {
return true;
}
}
}
};
You may only want to allow logged in users to read certain documents from the database. Context information is passed to the read
rule which can be inspected to determine login state.
module.exports = {
"default": {
"projects": {
"read": (req) => {
const { isLoggedIn } = req.client.auth;
Once you verify a user is logged in, you may also only want to allow them to read documents that belong to them. In addition to seeing the logged in user's information, you can see a snapshot of the document that is being read.
module.exports = {
"default": {
"projects": {
"read": (req, res) => {
const { isLoggedIn, data } = req.client.auth;
return (
!!isLoggedIn &&
data.id === res.data.owner
);
}
}
}
};
You may want to allow anyone to read a document, but only allow certain users to see privileged information on the document. For example, everyone can view a user's profile, but only that user can read their email address on the document.
module.exports = {
"default": {
"users": {
"read": (req, res) => {
const { isLoggedIn, data } = req.client.auth;
if (!isLoggedIn) {
return false;
}
if (data.id !== res.data.owner) {
delete res.data.email; // redact `email` property
}
return true;
}
}
}
};
In some cases, you may need to access other data in the database in order to validate an operation. Within the rules.js
file, you can use the Adamite SDK to query data just like you would on your client.
const adamite = require("@adamite/sdk").default;
module.exports = {
"default": {
"projects": {
"read": async (req, res) => {
const { isLoggedIn, data } = req.client.auth;
if (!isLoggedIn) {
throw new Error("Not logged in.");
}
const matchingOrganizations =
await adamite()
.database()
.collection("organizations")
.where("members", "array-includes", data.id)
.get();
if (matchingOrganizations.docs.length === 0) {
throw new Error("User does not belong to any organizations.");
}
const matchingOrganizationIds = matchingOrganizations.docs.map((o) => {
return o.id;
});
const projectOrganizationId = res.data.organization;
if (!matchingOrganizationIds.includes(projectOrganizationId)) {
throw new Error("User is not a member of project's organization.");
}
return true;
}
}
}
};