Prevent specific groups from directly accessing a table in AppGini

In some application scenarios, you might meet the usage case where you want one or more user groups to be able to access a table only if it’s displayed as a child table, but not directly as a master table.

Let’s take an example from the Northwind demo. Let’s say you have a users group named CustomerSupport and you don’t want that group to access the orders table unless they are accessing the orders of a specific customer. To clarify, you don’t want this group to directly access all orders like this:

This is the table view of the Orders table of the Northwind demo app. We want to prevent CustomerSupport users group from accessing this page.

However, you still want the group, when they choose a specific customer, to be able to access his orders like this:

The detail view of a specific customer, showing a list of their orders below. We want CustomerSupport users group to be able to access orders only through this page.

So, here is how to do this through a simple AppGini customization.

STEP 1/3: Remove the table link from the homepage

The first step would be to remove the link to the orders table from the homepage if the current user belongs to the CustomerSupport group. This is how the homepage for the Northwind demo looks like before any customization:

A screenshot of the homepage of Northwind app, highlighting the link to orders table that we want to remove for CustomerSupport group.

We’ll add the code for removing the link in hooks/footer-extras.php:

<?php
    $mi = getMemberInfo();
    // hide the table only if the user belongs to this group
    if($mi['group'] == 'CustomerSupport') {
        ?>
        <script>$j(funtion() {
           $j('#orders-tile').remove();
        })</script>
        <?php
    }
?>

Change CustomerSupport in the above code to the actual name of the concerned group. And change orders to the actual name of the table you want to remove the link for. If there are multiple groups you want to hide the link from, change the 4th line to something like this:

if(in_array($mi['group'], ['CustomerSupport', 'Sales', 'Example3'])) {

If you want to hide links to multiple tables rather than just one, change line 7 to something like this:

$j('#orders-tile, #products-tile, #table3-tile').remove();

STEP 2/3: Hide the table link from the navigation menu

The next step is to hide the link to orders table from the navigation menu for the CustomerSupport group. Here is how the navigation menu looks like by default:

The navigation menu of Northwind app. The link to orders table (highlighted) is what we want to remove for specific groups.

To remove that link, we could use a JavaScript statement like this:

$j('.nav a[href^=orders_view]').remove();

It basically tells the browser to remove the link to the orders_view.php page (which is the page showing the orders table) from the navigation bar. We could place that code line in the same code block we wrote in step 1 to avoid rewriting the if condition that checks for the user group. So, here is how our code in hooks/footer-extras.php should look like now:

<?php
    $mi = getMemberInfo();
    // hide the table only if the user belongs to this group
    if($mi['group'] == 'CustomerSupport') {
        ?>
        <script>$j(funtion() {
           $j('#orders-tile').remove();
           $j('.nav a[href^=orders_view]').remove();
        })</script>
        <?php
    }
?>

STEP 3/3: Prevent accessing the page unless it’s in embedded mode

So far, we’ve been using JavaScript code to hide the link to orders from a specific group. This basically hides the link, but doesn’t prevent the users from that group from accessing the orders table if they know how to type the link in the browser navigation bar.

In this step, we’ll actually add server-side code for effectively preventing the CustomerSupport group from accessing the orderstable, even if they manually type the link in the browser.

For doing this, we’ll use the orders_init hook function in hooks/orders.php. All we need to do is check if the current user belongs to the CustomerSupport group and if so, display an access denied message and return false. Returning false from the init hook prevents rendering any part of the table.

But, wait a minute! Do we really want to prevent CustomerSupport users from accessing the orders table entirely? Maybe we still want them to access the detail view of orders when they are viewing the info of a customer, and seeing a list of his orders in a child tab (see the second screenshot in this post). In order to allow this, we’ll need to check if the orders page is in embedded mode or not. Embedded mode is when a table is accessed from the child tab of a parent table, allowing displaying the detail view, but not the table view.

So, our orders_init code would finally read:

function orders_init(&$options, $memberInfo, &$args){
    // for users from CustomerSupport group in non-embedded mode, prevent access
    if($memberInfo['group'] == 'CustomerSupport' && empty($_REQUEST['Embedded'])) {
        echo '<div style="height: 4em;"></div>';
        echo '<div class="alert alert-danger">Access denied.</div>';
        return false;
    }

    return TRUE;
}

And if a user from CustomerSupport tries to access the orders page directly, this is what they’ll get:

Users from CustomerSupport group trying to directly access the orders table would now get an access denied error.

However, they’d be able to access orders of a specific customer by opening the customer details, scrolling down to his orders and clicking on any order to open in embedded mode.

I hope this was helpful. Please feel free to post questions, enhancements and comments below.

Published by Genedy

I'm the founder of BigProf Software. We're a tiny team of developers who create tools that make it easy (and affordable) for anyone to create connected business applications that work from any device with a browser.

Join the Conversation

2 Comments

  1. Hi Ahmed… i don’t know why but your workaround don’t work for me.
    This is the code that I put in footer extra file but nothin happen for the user in group “referenti_partner_special_ins-attiv_check-iscr_compil-cons-eventi”.
    Can you teel me where I go wrong? Thank you!

    $j(funtion() {
    $j(‘#partecipazione_riunione_evento_partner_e_non-tile’).remove();
    $j(‘.nav a[href^=partecipazione_riunione_evento_partner_e_non_view]’).remove();
    })

  2. SORRY!!! I find that in your tutorial there was “$j(funtion() {” instead on FUNCTION!!! I correct it and now it work! Thank you!

Leave a comment

Your email address will not be published. Required fields are marked *