Hide form block based on parameters from listed record

Hi.

I have a list-details page listing record information + a form block.
This form has the record-id as a hidden parameter and also this form is accessible only to logged-in users.

I need to show this form only to some logged-in users not all.

The listed record has 3 special fields in airtable:

user1:email1@domain.com,
user2:email2@domain.com,
user3:email3@domain.com

I need to show the form block only if logged-in user, is any of those emails.

To put it in other words, I need the form block to validate CONDITIONAL FILTERS (just like list-details block)

“Show list items to the users that match any of the following conditions”

user1 is Logged in User’s Email
OR
user2 is Logged in User’s Email
OR
user3 is Logged in User’s Email

Thank you so much for your help.

1 Like

Hi!
I may have the solution. But… I need more information about those three special fields.

  1. Why do you call them special?
  2. In order to let the condition be applied, those fields shouldn’t be empty? Like if there are not empty the conditional filter for the form visibility would apply?
  3. What are exactly those fields ? Domain ? Url ? other ?
  4. Last but not least, just to be clear, does it concern a fixed number of users, or this number will grow (or decrease) over the time and let’s say “everyday”?

Hi Mathieu

Sure.

  1. Those fields are just special to me or better to my app, they are regular airtable fields.
  2. ‘Empty or not’, should not be taken into consideration for hiding or showing the form block.
  3. Those fields are lookups. with email address as content.
  4. I am working on my app as saas model, so every account should only access their specific content.

Thanx for the help

Without visual elements, it’s hard :sweat_smile:

So, let’s try to dig in: those specific users have something in common, something that we could group them together in any way?

I can group them as needed do you want them on the same airtable field ?

Here is some graphical info

image

Ok, thanks! The lookup fields are related to a “link to another record” field type that is inside the users table?

I can’t refer to the user’s table for this to work, If I could, then it would be a matter of setting up permission groups.

Your use case is a tough one! I don’t think I have the solution (without custom code)
Let me suggest this thread, it might help: Hide or show blocks based on a record's attributes

That kind of helps is just that I have to find a way to evaluate if the loggedin users email, is present on one of those 3 airtable fields from the listed record.

Custome code is very welcome my dear.

Well, here it’s 1am in Paris, so no today for me :sweat_smile: and as I am a very beginner with Javascript…

=> Let’s make it simple: @Julien_Berawen or @dcoletta how to arrange this custom code (see above) with that specific use case?

I’m so tempted to replace “data value” by {LOGGED_IN_USER:EMAIL} … But 99% chance to be a bad idea :grin:

1 Like

Thank you so much for your help, I was thinking the same about replacing values :sweat_smile:
we are probably at the same javascript level…where trial and error is usually the way to go.

One thing I can say, this is very important for securing forms in softr apps. Very very.

If not, anyone logged in, could edit other users’ records, just by reading the record ids.

I can make the logic on airtable, to void such as malicious form submissions, but I want to actually prevent them from filling out the form.

Thanx again, and you better get some sleep.

Is this a situation where you are hiding some information for cosmetic purposes, or is it a matter of information security?

If the latter, then this problem isn’t amenable to a custom code solution. To be secure the data filtering needs to happen in the server.

Thank you David,

I don’t intend to hide info from my tables. I intend to hide a softr block which is kind of a static bloc, the form block

It doesn’t matter if people inspect the page and find the block. I just don’t want the form to work.

Also, I plan to add a second validation on the backend, to void malicious or not authorized submissions.

Hi guys,

@acjnas If the number of users who need to see the form is fixed and will always be three, you could use the code snippet in the post that @matthieu_chateau refered to and amend the condition like this :

if (
(document.querySelectorAll('div[data-mappedto="user_1"][data-value={LOGGED_IN_USER:EMAIL} i]').length > 0) || 
(document.querySelectorAll('div[data-mappedto="user_2"][data-value={LOGGED_IN_USER:EMAIL} i]').length > 0) || 
(document.querySelectorAll('div[data-mappedto="user_3"][data-value={LOGGED_IN_USER:EMAIL} i]').length > 0)
)

(I haven’t tested this exact syntax, it might require some light adaptation regarding the way you use {LOGGED_IN_USER:EMAIL} as a dynamic value for your condition).

For a more generic solution that could handle more or less users, I would first create a new airtable field that would concatenate all emails and use the presence of the logged-in user’s email within that field as a condition :

if (document.querySelectorAll('div[data-mappedto="users_who_should_see_the_form"][data-value*={LOGGED_IN_USER:EMAIL} i]').length > 0)

where users_who_should_see_the_form is the new field with all the emails.

Keep in mind that this would require that you first “display” on the page the values you use as conditions (user_1, user_2 and user_3 in the first option, users_who_should_see_the_form in the second option).
You can insert them and render them invisible with hidden or collapse.

You should check first that your fields render the needed value as a string for the email adress, if they’re lookups they might not and have their value send the user’s recordId instead. To do that, after you’ve inserted the fields on your page, you can use the Inspector within your browser and check if the data-value attribute on your fields is indeed an email (or several emails within a string in the second option).

Also keep in mind @dcoletta 's warning as this is in no way a secure solution to prevent unauthorized users to input data in your form.

2 Likes

Thanx for the help Julien.

Before testing the script, I simply added a new email field to the table: ‘validEmail’ and manually entered the user email address that I expect to grant permission to access the form.

I have the need to hide two form blocks: form-es and form-en

Then I went to page custom code ==> footer and added this code:

<script>
//Hide form if 'validEmail' is different from logged-in user email
    
    document.addEventListener("DOMContentLoaded", function() {    
        var waitForData = setInterval(function () {
            if (typeof $ != 'undefined') {
                if (document.querySelectorAll('div[data-mappedto="validEmail"][data-value*={LOGGED_IN_USER:EMAIL} i]').length > 0) {
                    
                    var form1 = document.getElementById('form-es');
                    var form2 = document.getElementById('form-en');
                    form1.style.display = 'none';
                    form2.style.display = 'none';

                    
                    clearInterval(waitForData);
                }
            }
        }, 100);
    });
</script>

Then no matter the case, every logged-in user to my app can access the form.

Hey folks,

would this work ?

<script>    
    document.addEventListener("DOMContentLoaded", function() {    
        var waitForData = setInterval(function () {
            if (typeof $ != 'undefined') {
                const recordId = getUrlParam('recordId');
                if (window.records && window.records[recordId] && window.records[recordId].record.fields['fieldName'] === 'YourValue') {
                    
                    var form1 = document.getElementById('form-es');
                    var form2 = document.getElementById('form-en');
                    form1.style.display = 'none';
                    form2.style.display = 'none';

                    
                    clearInterval(waitForData);
                }
            }
        }, 100);

        function getUrlParam(name) {
            const url = new URL(window.location.href);
            let param;
            for(var key of url.searchParams.keys()) {
                if(key.toLowerCase() === name.toLowerCase()) {
                param = url.searchParams.get(name);
                break;
                }
            }
        
            if(!param && name.toLowerCase() === 'recordid') {
                param = getRecordIdFromPath();
            }
            return param;
        }
        
        function getRecordIdFromPath() {
            let pathName = window.location.pathname;
            if (pathName.indexOf('/r/rec') !== -1) {
                pathName = pathName.substr(pathName.indexOf('/r/rec') + 3);
                if (pathName.indexOf("/") !== -1) {
                pathName = pathName(0, pathName.indexOf('/'))
                }
                return pathName;
            }
            return undefined;
        }
    });
</script>

You need to play with FieldName, YourValue and Form Ids.

2 Likes

Hey,

  1. For future reference, the code that ended up solving @acjnas’ problem :
<script>
//Hide forms if 'validEmail' includes the logged-in user's email
    
    document.addEventListener("DOMContentLoaded", function() {    
        var waitForData = setInterval(function () {
            if (typeof $ != 'undefined') {
                var userEmail=window['logged_in_user']['softr_user_email'];
                if (document.querySelectorAll('div[data-mappedto="validEmail"][data-value*=' + CSS.escape(userEmail) + ' i]').length > 0) {
                    
                    var form1 = document.getElementById('form-es');
                    var form2 = document.getElementById('form-en');
                    form1.style.display = 'none';
                    form2.style.display = 'none';

                    
                    clearInterval(waitForData);
                }
            }
        }, 100);
    });
</script>
  1. @artur That looks very promising ! Does that mean we can use window.records[recordId].record.fields['fieldName'] to query any field from the current recordID, even though that specific field is not part of the page ? Is there a way to circumvent that to prevent users from querying any field on the table ?
2 Likes

Right now if the user can see the record the fields will be accessible, although in two weeks only visible fields will be available.

3 Likes