This is a quick reply to a question that has been asked on Velo's discord.
In my last post, we spoke about the difference between js and jsw files. We are now going to see how we use them to secure our backend and prevent unauthorized action. Let's say we have a Velo app that let you manage a user profile. The business rules are as follows:
Anyone can see a user's public profile
User can update their own profile
Moderators can update any user's profile
Only Admin can delete a profile
We are going to store our logic to manipulate users(read, update, delete) in a file `backend/repositories/users.js` and expose those actions via our web module `backend/webModules/users.jsw`.
backend/webModules/users.jsw
import {deleteUser, updateUser, readUser} from "backend/repositories/user.js"
// This can be accessed by anyone
export async function getPublicProfile(userId) {
const userProfile = await readUser(userId);
//Remove private information
userProfile.email = "";
userProfile.address = "";
return userProfile;
}
// Using jsw permissions' settings, you can restrict execution to only admins
export function removeUser(userId) {
return deleteUser(userId)
}
// Only allow users to edit their own profile or with the role "moderator" to edit the user
export async function editProfile(updatedProfile) {
const currentUser = await getCurrentUser();
const currentUserRoles = await getCurrentUserRole();
if(updatedUser._id !== currentUser._id && !currentUserRoles.includes("moderator")) throw new Error("unauthorized");
return updateUser(updatedUser);
}
the file `backend/repositories/users` simply uses wixData to retrieve, update and delete a user.
This approach guarantees a single point of entry for all operations regarding the user profile. Then you only need to verify credentials within the jsw file. Having a single point of entry also makes it easier to maintain security rules as the project evolves.
Finally, This effectively separated security from logic and allows us to reuse the user's repositories across several use cases.
For instance, let's say we want to allow an API call to retrieve a user profile via the route `GET /user/{id}` then we can reuse our code from "backend/repositories/users" without any modification and only check that the API call has a valid api-key.
Learn more:
Comments