TUTORIAL: How to bypass Collection Permissions and Hooks.

Hello everyone :raised_hand_with_fingers_splayed:

In the past couple months, I’ve encountered a lot of questions from people when they try to read or write data on collections they don’t have permissions to .

I won’t be able to cover all the possible scenarios but I’ll try my best, but before we continue, you need to know what are Hooks, and how they are used, if you already know, you can skip this section to the next one.

If you only want to know how to bypass them, head over to Section 4 below.


Section 1: What are hooks?

Data hooks run code before or after certain interactions with your site’s collections. A data hook allows you to intercept the interaction immediately before or immediately after it occurs. The hook’s code can even be used to affect the interaction itself. For example, you may want to intercept an item before it is added to your collection to perform a final validation or to tweak the data that actually makes it into the collection.

To learn more, visit these useful links.


Section 2: Why would you want to bypass the hooks?

You might want to intercept the data insertion or extraction in some scenarios, for example, a form where users submit their data will trigger an beforeInsert() event to edit certain data or validate it, or an afterUpdate( ) event to send email notification to users when they update their data, but in some cases, you don’t want to send email notification to users when YOU update their data, or you may not want to perform a beforeInsert() processing on data that you KNOW for sure is already processed or don’t need processing.

Learn more about Data Hooks here.


Section 3: Collection Permissions

You should always set the permissions of your database collections to be as restrictive as possible. Each permission should only be granted to the Admin role unless there is a specific reason to grant the permission to additional roles. Even when there is a reason to grant a permission to more roles, you should only grant it to the roles that need it.

Here are some examples to illustrate this point:

  • Form Submission - Suppose you have an input form that you want anyone to be able to use. On the collection that the form is connected to, you need to set the create permissions to the Anyone role. But you should still keep all the other permissions restricted to only the Admin role.

  • Read - Admin

  • Create - Anyone

  • Update - Admin

  • Delete - Admin

  • Site Content - Suppose you have a page that displays content from a collection to anyone. You need to set the read permission of that collection to the Anyone role. But you should still keep all the other permissions restricted to only the Admin role.

  • Read - Anyone

  • Create - Admin

  • Update - Admin

  • Delete - Admin

  • Member-Generated Content - Suppose you have a member-generated comments section where members can post comments that anyone can see, but only the poster can update or delete the comment. You should to set the permissions as follows.

  • Read - Anyone

  • Create - Site member

  • Update - Site member author

  • Delete - Site member author

To learn more about Collection Permissions, please visit this page:


Section 4: How to bypass the Hooks & Permissions

You can only bypass the Hooks and Permissions from the Backend side, by passing an object as the options parameter that modifies how an operation is performed.

The options object has one or both of the following key:value pairs:

  • “suppressAuth”: true / false

  • “suppressHooks”: true / false

let options = {
  "suppressAuth": true, // Setting this option to true will bypass the permissions.
  "suppressHooks": true // Setting this option to true will bypass the hooks.
};

You can read more about WixDataOptions here.

Now, how to use options object in our code? I’ll throw a different example than the one in the link above.

import wixData from 'wix-data';

let options = {
  "suppressAuth": true,
  "suppressHooks": true
};

wixData.query("myCollection")
  .find(options) // We pass the options object to the find() function
  .then( (results) => {
    if(results.items.length > 0) {
      let firstItem = results.items[0]; //see item below
    } else {
      // handle case where no matching items found
    }
  } )
  .catch( (err) => {
    let errorMsg = err;
  } );

Here’s an example on how to bypass the permissions of the Members collection:

1. Create New Web Module and name it “getMemberDetails”.

2. Import WixData to the web modual (Back-end Code).

import wixData from 'wix-data';

3. Create a function that has a query inside it, make sure you add the export word before it or the function will not be called from the Front-end.

export function getMemberID(ownerID) {

 // This bypasses the permissions check so the query can run for any user, not just the Member who owns the asset
 let options = {
    "suppressAuth": true
 }

 // This runs the query with the above option in place and finds the Member who's ID matches the _owner ID of the Item displayed on the dynamic page
 return wixData.query('Members/PrivateMembersData')
        .eq('_id', ownerID)
        .find(options)
}

The ownerID is the ID that we pass to this function from the Front-end code.
If you only want to return specific data, use the following code:

return wixData.query('Members/PrivateMembersData').eq('_id', ownerID)
    .find(options)
    .then((result) => {
        let item = result.items[0];      
        
        let finalResult = {
            name: item.nickname,
            email: item.loginEmail
        }
        
        return finalResult;
    })

I’ll continue my example assuming that we used the above code.
NOTE: All the above code is written on the web module we’ve created earlier on the Back-end.

Front-end code:

4. Start by importing the Wix-Users and our module.

import wixUsers from 'wix-users';
import { getMemberID } from 'backend/getMemberDetails.jsw';

5. Create a function that will call the function from the Back-end to run and return its data.

function getDetails() {
       
}

6. Call the function from the web module that we’ve imported in step 4 inside the function we created in step 5.

function getDetails() {
       return getMemberID(wixUsers.currentUser.id).then((result) => {
              let name = result.name;
              let email = result.email;
       })
}

That’s it, hope you find this tutorial useful, if you did, hit the :heart: button below.
If you have any related questions drop them in the comments down below.

Ahmad

5 Likes

On step 3, the line where it says

return finalResutl;
//it should be finalResult not finalResutl 
please fix this.😉

Thank you for your note, it was written quickly without proofing, it’s fixed now.
Thank you :wink:

Also I got an error in my code. The bit where I got the error(step 3) is the

return finalResutl;

I got the error massage on the return bit. I will copy my code.

import wixData from 'wix=data';

export function getMemberId(ownerId) {

 let options = {
 "suppressAuth": true
    }
 return wixData.query('PrivateMembersData')
    .eq('_id', ownerId)
    .find(options)
    .then((result) => {
 let item = result.items[0];
        name: item.nickname,
        email = item.loginEmail
    }
 return final result;
)}

import wixUsers from 'wix-users';
import {getMemberId} from 'backend/getMemberDetails.jsw';
function getDetails() {
 return getMemberId(wixUsers.currentUser.id).then((result) => {
 let name = result.name;
 let email = result.email;
    })


You’re putting all the code in the Back-end , which is wrong, some of it should be on the Back-end and the rest on the Front-end , the front-end code is starting from step 4, you need to include that part on the page itself, not on the Back-end .

I got it!:grinning:

Also, please correct the word “finalResult” without space
Instead of:

return final result;

Use

return finalResult;

also I think step 4(the ID should be Id?)

import { getMemberID } from 'backend/getMemberDetails.jsw';

should be

import { getMemberId } from 'backend/getMemberDetails.jsw';

I have copied the code. I think I have some code I don’t need.

import wixUsers from 'wix-users';
import { getMemberID} from 'backend/getMemberDetails.jsw';
functin getDetails() {
 return getMemberID(wixUsers.currentUser.id).then((result) => {
 let name = result.name;
 let email = result.email;
    })
}
 
 let user = wixUsers.currentUser;

$w.onReady(function () {
if (user.loggedIn) { getUserDetails() }
})  
 
 async function getUserDetails() {
 return wixData.query('PrivateMembersData')
     .eq('_id', user.id).find().then((result) => {
 let item = result.items[0]
 let email = item.nickname;
 let name = item.loginEmail; 
 
     $w('#input2').value = name;
     $w('#input3').value = email;
     }).catch((err) => {
         console.warn('searching the database failed!')
         console.error(err);
     })

 
 
}

I also got an error message on the step 6

function getDetails() {

I got the error message on the getDetails.

Look how it’s written in the Back-end code.

You’re writing it incorrectly, you’re missing the last letters in your original code

function getDetails() {

You’re missing the o letter

Front-end code

import wixUsers from 'wix-users';
import { getMemberID } from 'backend/getMemberDetails.jsw';
 
let user = wixUsers.currentUser;

$w.onReady(function () {
      if (user.loggedIn) { getUserDetails() }
})  
 
async function getUserDetails() {
       await getMemberID(user.id).then((result) => {
              let name = result.name;
              let email = result.email;
              
              $w('#input2').value = name;
              $w('#input3').value = email;
       })
}

I think I still have some more errors. I got the error on the last ).

import wixUsers from 'wix-users';
import { getMemberId} from 'backend/getMemberDetails.jsw';
let user = wixUsers.currentUser;

$w.onReady(function () {
 if (user.loggedIn) {getUserDetails() }
})
function getDetails() {
 return
     getMemberId(wixUsers.currentUser.id).then((result) => {
 let name = result.name;
 let email = result.email;
 
$w('#input2').value = name;
$w('#input3').value = email;
})
)  //here is the ) where I got the error message.
  //I will sleep now.😴
  //Arthur