From fee338c9d6ad3fd828274ef322f012049327dea4 Mon Sep 17 00:00:00 2001
From: TangoBeee <zonebattle90@gmail.com>
Date: Thu, 6 Jun 2024 10:06:21 +0530
Subject: [PATCH 01/24] feat: updated old role based access control
 implementation

---
 .../com/akto/action/AdminSettingsAction.java  |  11 --
 .../main/java/com/akto/action/TeamAction.java |  80 ++++++-------
 .../com/akto/action/user/AzureSsoAction.java  |  17 ---
 .../com/akto/action/user/GithubSsoAction.java |  30 -----
 .../com/akto/action/user/OktaSsoAction.java   |  17 ---
 .../interceptor/RoleAccessInterceptor.java    |  83 +++++++++++++
 .../com/akto/interceptor/RoleHierarchy.java   |  26 +++++
 apps/dashboard/src/main/resources/struts.xml  | 109 ++++++++++++++++++
 8 files changed, 255 insertions(+), 118 deletions(-)
 create mode 100644 apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java
 create mode 100644 apps/dashboard/src/main/java/com/akto/interceptor/RoleHierarchy.java

diff --git a/apps/dashboard/src/main/java/com/akto/action/AdminSettingsAction.java b/apps/dashboard/src/main/java/com/akto/action/AdminSettingsAction.java
index 5f19ce3ceb..c81b634c36 100644
--- a/apps/dashboard/src/main/java/com/akto/action/AdminSettingsAction.java
+++ b/apps/dashboard/src/main/java/com/akto/action/AdminSettingsAction.java
@@ -91,13 +91,6 @@ public String toggleNewMergingEnabled() {
     public String toggleTelemetry() {
         if (!DashboardMode.isOnPremDeployment()) return Action.ERROR.toUpperCase();
 
-        User user = getSUser();
-        if (user == null) return ERROR.toUpperCase();
-        boolean isAdmin = RBACDao.instance.isAdmin(user.getId(), Context.accountId.get());
-        if (!isAdmin) {
-            addActionError("Only admin can add change this setting");
-            return Action.ERROR.toUpperCase();
-        }
         AccountSettings accountSettings = AccountSettingsDao.instance.findOne(AccountSettingsDao.generateFilter());
         TelemetrySettings telemetrySettings = accountSettings.getTelemetrySettings();
         telemetrySettings.setCustomerEnabled(enableTelemetry);
@@ -141,10 +134,6 @@ public String updateTrafficAlertThresholdSeconds() {
 
     private boolean redactPayload;
     public String toggleRedactFeature() {
-        User user = getSUser();
-        if (user == null) return ERROR.toUpperCase();
-        boolean isAdmin = RBACDao.instance.isAdmin(user.getId(), Context.accountId.get());
-        if (!isAdmin) return ERROR.toUpperCase();
 
         AccountSettingsDao.instance.getMCollection().updateOne(
                 AccountSettingsDao.generateFilter(),
diff --git a/apps/dashboard/src/main/java/com/akto/action/TeamAction.java b/apps/dashboard/src/main/java/com/akto/action/TeamAction.java
index 50245c943b..9b362623a0 100644
--- a/apps/dashboard/src/main/java/com/akto/action/TeamAction.java
+++ b/apps/dashboard/src/main/java/com/akto/action/TeamAction.java
@@ -81,55 +81,49 @@ private enum ActionType {
     String email;
     public String performAction(ActionType action) {
         int currUserId = getSUser().getId();
-        boolean isAdmin = RBACDao.instance.isAdmin(currUserId, Context.accountId.get());
-        if (!isAdmin) {
-            addActionError("You are not authorized to perform this action");
-            return Action.ERROR.toUpperCase();
-        } else {
-            int accId = Context.accountId.get();
-
-            Bson findQ = Filters.eq(User.LOGIN, email);
-            User userDetails = UsersDao.instance.findOne(findQ);
-            boolean userExists =  userDetails != null;
-            if (userExists && userDetails.getId() == currUserId) {
-                addActionError("You cannot perform this action on yourself");
-                return Action.ERROR.toUpperCase();
-            }
+        int accId = Context.accountId.get();
 
-            switch (action) {
-                case REMOVE_USER:
-                    if (userExists) {
-                        UsersDao.instance.updateOne(findQ, Updates.unset("accounts." + accId));
-                        RBACDao.instance.deleteAll(
-                                Filters.and(
-                                        Filters.eq(RBAC.USER_ID, userDetails.getId()),
-                                        Filters.eq(RBAC.ACCOUNT_ID, accId)));
-                        return Action.SUCCESS.toUpperCase();
-                    } else {
-                        DeleteResult delResult = PendingInviteCodesDao.instance.getMCollection().deleteMany(Filters.eq("inviteeEmailId", email));
-                        if (delResult.getDeletedCount() > 0) {
-                            return Action.SUCCESS.toUpperCase();
-                        } else {
-                            return Action.ERROR.toUpperCase();
-                        }
-                    }
+        Bson findQ = Filters.eq(User.LOGIN, email);
+        User userDetails = UsersDao.instance.findOne(findQ);
+        boolean userExists =  userDetails != null;
+        if (userExists && userDetails.getId() == currUserId) {
+            addActionError("You cannot perform this action on yourself");
+            return Action.ERROR.toUpperCase();
+        }
 
-                case MAKE_ADMIN:
-                    if (userExists) {
-                        RBACDao.instance.updateOne(
-                                Filters.and(
-                                        Filters.eq(RBAC.USER_ID, userDetails.getId()),
-                                        Filters.eq(RBAC.ACCOUNT_ID, accId)),
-                                Updates.set(RBAC.ROLE, Role.ADMIN));
+        switch (action) {
+            case REMOVE_USER:
+                if (userExists) {
+                    UsersDao.instance.updateOne(findQ, Updates.unset("accounts." + accId));
+                    RBACDao.instance.deleteAll(
+                            Filters.and(
+                                    Filters.eq(RBAC.USER_ID, userDetails.getId()),
+                                    Filters.eq(RBAC.ACCOUNT_ID, accId)));
+                    return Action.SUCCESS.toUpperCase();
+                } else {
+                    DeleteResult delResult = PendingInviteCodesDao.instance.getMCollection().deleteMany(Filters.eq("inviteeEmailId", email));
+                    if (delResult.getDeletedCount() > 0) {
                         return Action.SUCCESS.toUpperCase();
                     } else {
-                        addActionError("User doesn't exist");
                         return Action.ERROR.toUpperCase();
                     }
-
-                default:
-                    break;
-            }
+                }
+
+            case MAKE_ADMIN:
+                if (userExists) {
+                    RBACDao.instance.updateOne(
+                            Filters.and(
+                                    Filters.eq(RBAC.USER_ID, userDetails.getId()),
+                                    Filters.eq(RBAC.ACCOUNT_ID, accId)),
+                            Updates.set(RBAC.ROLE, Role.ADMIN));
+                    return Action.SUCCESS.toUpperCase();
+                } else {
+                    addActionError("User doesn't exist");
+                    return Action.ERROR.toUpperCase();
+                }
+
+            default:
+                break;
         }
         return Action.SUCCESS.toUpperCase();
     }
diff --git a/apps/dashboard/src/main/java/com/akto/action/user/AzureSsoAction.java b/apps/dashboard/src/main/java/com/akto/action/user/AzureSsoAction.java
index 357a37eacb..ba2c000df4 100644
--- a/apps/dashboard/src/main/java/com/akto/action/user/AzureSsoAction.java
+++ b/apps/dashboard/src/main/java/com/akto/action/user/AzureSsoAction.java
@@ -6,7 +6,6 @@
 
 import com.akto.action.UserAction;
 import com.akto.dao.ConfigsDao;
-import com.akto.dao.RBACDao;
 import com.akto.dao.UsersDao;
 import com.akto.dao.context.Context;
 import com.akto.dto.Config;
@@ -33,14 +32,6 @@ public String addAzureSsoInfo(){
             return ERROR.toUpperCase();
         }
 
-        User user = getSUser();
-        if (user == null) return ERROR.toUpperCase();
-        boolean isAdmin = RBACDao.instance.isAdmin(user.getId(), Context.accountId.get());
-        if (!isAdmin) {
-            addActionError("Only admin can add SSO");
-            return Action.ERROR.toUpperCase();
-        }
-
         if (SsoUtils.isAnySsoActive()) {
             addActionError("A SSO Integration already exists.");
             return ERROR.toUpperCase();
@@ -65,14 +56,6 @@ public String deleteAzureSso(){
             return ERROR.toUpperCase();
         }
 
-        User user = getSUser();
-        if (user == null) return ERROR.toUpperCase();
-        boolean isAdmin = RBACDao.instance.isAdmin(user.getId(), Context.accountId.get());
-        if (!isAdmin) {
-            addActionError("Only admin can delete SSO");
-            return Action.ERROR.toUpperCase();
-        }
-
         DeleteResult result = ConfigsDao.instance.deleteAll(Filters.eq("_id", "AZURE-ankush"));
 
         if (result.getDeletedCount() > 0) {
diff --git a/apps/dashboard/src/main/java/com/akto/action/user/GithubSsoAction.java b/apps/dashboard/src/main/java/com/akto/action/user/GithubSsoAction.java
index c458bf6d17..6797b63673 100644
--- a/apps/dashboard/src/main/java/com/akto/action/user/GithubSsoAction.java
+++ b/apps/dashboard/src/main/java/com/akto/action/user/GithubSsoAction.java
@@ -4,7 +4,6 @@
 import com.akto.action.testing.StartTestAction;
 import com.akto.dao.AccountSettingsDao;
 import com.akto.dao.ConfigsDao;
-import com.akto.dao.RBACDao;
 import com.akto.dao.UsersDao;
 import com.akto.dao.context.Context;
 import com.akto.dto.AccountSettings;
@@ -44,14 +43,6 @@ public String deleteGithubSso() {
             return ERROR.toUpperCase();
         }
 
-        User user = getSUser();
-        if (user == null) return ERROR.toUpperCase();
-        boolean isAdmin = RBACDao.instance.isAdmin(user.getId(), Context.accountId.get());
-        if (!isAdmin) {
-            addActionError("Only admin can delete SSO");
-            return ERROR.toUpperCase();
-        }
-
         DeleteResult result = ConfigsDao.instance.deleteAll(Filters.eq("_id", "GITHUB-ankush"));
 
         if (result.getDeletedCount() > 0) {
@@ -77,13 +68,6 @@ public String deleteGithubAppSecretKey() {
             return ERROR.toUpperCase();
         }
 
-        User user = getSUser();
-        boolean isAdmin = RBACDao.instance.isAdmin(user.getId(), Context.accountId.get());
-        if (!isAdmin) {
-            addActionError("Only admin can delete github app credentials");
-            return ERROR.toUpperCase();
-        }
-
         AccountSettingsDao.instance.updateOne(generateFilter(), Updates.combine(
                 Updates.unset(AccountSettings.GITHUB_APP_ID),
                 Updates.unset(AccountSettings.GITHUB_APP_SECRET_KEY)));
@@ -97,12 +81,6 @@ public String addGithubAppSecretKey() {
             return ERROR.toUpperCase();
         }
 
-        User user = getSUser();
-        boolean isAdmin = RBACDao.instance.isAdmin(user.getId(), Context.accountId.get());
-        if (!isAdmin) {
-            addActionError("Only admin can delete github app credentials");
-            return ERROR.toUpperCase();
-        }
         githubAppSecretKey = githubAppSecretKey.replace("-----BEGIN RSA PRIVATE KEY-----","");
         githubAppSecretKey = githubAppSecretKey.replace("-----END RSA PRIVATE KEY-----","");
         githubAppSecretKey = githubAppSecretKey.replace("\n","");
@@ -133,14 +111,6 @@ public String addGithubSso() {
             return ERROR.toUpperCase();
         }
 
-        User user = getSUser();
-        if (user == null) return ERROR.toUpperCase();
-        boolean isAdmin = RBACDao.instance.isAdmin(user.getId(), Context.accountId.get());
-        if (!isAdmin) {
-            addActionError("Only admin can add SSO");
-            return ERROR.toUpperCase();
-        }
-
         if (SsoUtils.isAnySsoActive()) {
             addActionError("A SSO Integration already exists.");
             return ERROR.toUpperCase();
diff --git a/apps/dashboard/src/main/java/com/akto/action/user/OktaSsoAction.java b/apps/dashboard/src/main/java/com/akto/action/user/OktaSsoAction.java
index 8cd2b16674..23dec2273f 100644
--- a/apps/dashboard/src/main/java/com/akto/action/user/OktaSsoAction.java
+++ b/apps/dashboard/src/main/java/com/akto/action/user/OktaSsoAction.java
@@ -4,7 +4,6 @@
 
 import com.akto.action.UserAction;
 import com.akto.dao.ConfigsDao;
-import com.akto.dao.RBACDao;
 import com.akto.dao.UsersDao;
 import com.akto.dao.context.Context;
 import com.akto.dto.Config;
@@ -31,14 +30,6 @@ public String addOktaSso() {
             return ERROR.toUpperCase();
         }
 
-        User user = getSUser();
-        if (user == null) return ERROR.toUpperCase();
-        boolean isAdmin = RBACDao.instance.isAdmin(user.getId(), Context.accountId.get());
-        if (!isAdmin) {
-            addActionError("Only admin can add SSO");
-            return ERROR.toUpperCase();
-        }
-
         if (SsoUtils.isAnySsoActive()) {
             addActionError("A SSO Integration already exists.");
             return ERROR.toUpperCase();
@@ -62,14 +53,6 @@ public String deleteOktaSso() {
             return ERROR.toUpperCase();
         }
 
-        User user = getSUser();
-        if (user == null) return ERROR.toUpperCase();
-        boolean isAdmin = RBACDao.instance.isAdmin(user.getId(), Context.accountId.get());
-        if (!isAdmin) {
-            addActionError("Only admin can delete SSO");
-            return ERROR.toUpperCase();
-        }
-
         DeleteResult result = ConfigsDao.instance.deleteAll(Filters.eq("_id", "OKTA-ankush"));
 
         if (result.getDeletedCount() > 0) {
diff --git a/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java b/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java
new file mode 100644
index 0000000000..7ca2d0edf0
--- /dev/null
+++ b/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java
@@ -0,0 +1,83 @@
+package com.akto.interceptor;
+
+import com.akto.dao.RBACDao;
+import com.akto.dto.User;
+import com.akto.log.LoggerMaker;
+import com.akto.util.DashboardMode;
+import com.mongodb.client.model.Filters;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class RoleAccessInterceptor extends AbstractInterceptor {
+
+    private static final LoggerMaker loggerMaker = new LoggerMaker(RoleAccessInterceptor.class, LoggerMaker.LogDb.DASHBOARD);
+
+    String rolesList;
+
+    public final static String FORBIDDEN = "FORBIDDEN";
+    private final static String USER_ID = "userId";
+    private final static String USER = "user";
+
+    public void setRolesList(String rolesList) {
+        this.rolesList = rolesList;
+    }
+
+    @Override
+    public String intercept(ActionInvocation invocation) throws Exception {
+        try {
+            if(!DashboardMode.isMetered()) {
+                return invocation.invoke();
+            }
+
+            if(rolesList == null || rolesList.trim().isEmpty()) {
+                throw new Exception("Roles list is null or empty");
+            }
+
+            List<String> roles = Arrays.stream(rolesList.split(" "))
+                                        .map(String::trim)
+                                        .map(String::toUpperCase)
+                                        .collect(Collectors.toList());
+
+            Map<String, Object> session = invocation.getInvocationContext().getSession();
+            User user = (User) session.get(USER);
+
+            if(user == null) {
+                throw new Exception("User not found in session");
+            }
+
+            int userId = user.getId();
+
+            String userRole = RBACDao.instance.findOne(Filters.eq(USER_ID, userId)).getRole().name().toUpperCase();
+
+            if(userRole == null || userRole.isEmpty()) {
+                throw new Exception("User role not found");
+            }
+
+            boolean hasRequiredRole = false;
+
+            for(String requiredRole : roles) {
+                if (RoleHierarchy.hasRole(userRole, requiredRole)) {
+                    hasRequiredRole = true;
+                    break;
+                }
+            }
+
+            if(!hasRequiredRole) {
+                ((ActionSupport) invocation.getAction()).addActionError("The role '" + userRole + "' does not have access.");
+                return FORBIDDEN;
+            }
+        } catch(Exception e) {
+            String api = invocation.getProxy().getActionName();
+            String error = "Error in RoleInterceptor for api: " + api + " ERROR: " + e.getMessage();
+            loggerMaker.errorAndAddToDb(e, error, LoggerMaker.LogDb.DASHBOARD);
+        }
+
+        return invocation.invoke();
+    }
+}
diff --git a/apps/dashboard/src/main/java/com/akto/interceptor/RoleHierarchy.java b/apps/dashboard/src/main/java/com/akto/interceptor/RoleHierarchy.java
new file mode 100644
index 0000000000..9f39ae77c2
--- /dev/null
+++ b/apps/dashboard/src/main/java/com/akto/interceptor/RoleHierarchy.java
@@ -0,0 +1,26 @@
+package com.akto.interceptor;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class RoleHierarchy {
+    private static final Map<String, String[]> hierarchy = new HashMap<>();
+
+    static {
+        hierarchy.put("ADMIN", new String[]{"ADMIN", "MEMBER"});
+        hierarchy.put("MEMBER", new String[]{"MEMBER"});
+    }
+
+    public static boolean hasRole(String userRole, String requiredRole) {
+        String[] roles = hierarchy.get(userRole);
+        if (roles == null) {
+            return false;
+        }
+        for (String role : roles) {
+            if (role.equalsIgnoreCase(requiredRole)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/apps/dashboard/src/main/resources/struts.xml b/apps/dashboard/src/main/resources/struts.xml
index 73186271b8..b6c8560290 100644
--- a/apps/dashboard/src/main/resources/struts.xml
+++ b/apps/dashboard/src/main/resources/struts.xml
@@ -15,6 +15,7 @@
         <interceptors>
             <!-- The feature labels for the usage interceptor are defined in stigg feature -> metadata. -->
             <interceptor name="usageInterceptor" class="com.akto.interceptor.UsageInterceptor" />
+            <interceptor name="roleAccessInterceptor" class="com.akto.interceptor.RoleAccessInterceptor" />
             <interceptor name="collectionInterceptor" class="com.akto.interceptor.CollectionInterceptor" />
         </interceptors>
 
@@ -217,6 +218,15 @@
         <action name="api/removeUser" class="com.akto.action.TeamAction" method="removeUser">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="rolesList">ADMIN</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="httpheader">
                 <param name="status">401</param>
@@ -226,6 +236,15 @@
         <action name="api/makeAdmin" class="com.akto.action.TeamAction" method="makeAdmin">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="rolesList">ADMIN</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -295,6 +314,15 @@
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">AKTO_SSO</param>
             </interceptor-ref>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="rolesList">ADMIN</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -314,6 +342,15 @@
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">AKTO_SSO</param>
             </interceptor-ref>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="rolesList">ADMIN</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -344,6 +381,15 @@
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">AKTO_SSO</param>
             </interceptor-ref>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="rolesList">ADMIN</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -363,6 +409,15 @@
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">AKTO_SSO</param>
             </interceptor-ref>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="rolesList">ADMIN</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -393,6 +448,15 @@
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">AKTO_SSO</param>
             </interceptor-ref>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="rolesList">ADMIN</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -412,6 +476,15 @@
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">AKTO_SSO</param>
             </interceptor-ref>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="rolesList">ADMIN</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -450,6 +523,15 @@
         <action name="api/addGithubAppSecretKey" class="com.akto.action.user.GithubSsoAction" method="addGithubAppSecretKey">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="rolesList">ADMIN</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -461,6 +543,15 @@
         <action name="api/deleteGithubAppSecretKey" class="com.akto.action.user.GithubSsoAction" method="deleteGithubAppSecretKey">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="rolesList">ADMIN</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1545,6 +1636,15 @@
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">API_DATA_REDACTION</param>
             </interceptor-ref>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="rolesList">ADMIN</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="httpheader">
                 <param name="status">401</param>
@@ -1894,6 +1994,15 @@
         <action name="api/toggleTelemetry" class="com.akto.action.AdminSettingsAction" method="toggleTelemetry">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="rolesList">ADMIN</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>

From 1759e15b2a29f5693164952d7268ebfc42b22f08 Mon Sep 17 00:00:00 2001
From: shivamrawat101192 <shivam@akto.io>
Date: Wed, 12 Jun 2024 11:41:03 +0530
Subject: [PATCH 02/24] rbac initial enums for handling of groups and features

---
 libs/dao/src/main/java/com/akto/dto/RBAC.java | 129 +++++++++++++++++-
 1 file changed, 128 insertions(+), 1 deletion(-)

diff --git a/libs/dao/src/main/java/com/akto/dto/RBAC.java b/libs/dao/src/main/java/com/akto/dto/RBAC.java
index f1c8b2ddc5..d2c1aadc74 100644
--- a/libs/dao/src/main/java/com/akto/dto/RBAC.java
+++ b/libs/dao/src/main/java/com/akto/dto/RBAC.java
@@ -3,6 +3,8 @@
 
 import org.bson.types.ObjectId;
 
+import java.util.*;
+
 public class RBAC {
 
     private ObjectId id;
@@ -15,7 +17,132 @@ public class RBAC {
     public static final String ACCOUNT_ID = "accountId";
 
     public enum Role {
-        ADMIN, MEMBER
+        ADMIN("ADMIN"),
+        MEMBER("SECURITY ENGINEER"),
+        DEVELOPER("DEVELOPER"),
+        GUEST("GUEST");
+
+        final String name;
+        final Role[] allowedAccess;//invitation
+        final AccessGroups[] allowedAccessForRole;
+
+
+        Role(String name) {
+            this.name = name;
+            this.allowedAccess = Role.allowedAccess(this);
+            this.allowedAccessForRole = Role.createAccessGroupsForRole(this);
+        }
+
+        private static AccessGroups[] createAccessGroupsForRole(Role role) {
+            switch (role) {
+                case ADMIN:
+                    return new AccessGroups[]{
+                            AccessGroups.INVENTORY
+                                    .addFeature(Feature.API_COLLECTIONS.setWriteType(WriteType.READ_WRITE))
+                                    .addFeature(Feature.SENSITIVE_DATA.setWriteType(WriteType.READ_WRITE))
+                                    .addFeature(Feature.TRAFFIC_FILTERS.setWriteType(WriteType.READ_WRITE))
+                                    .addFeature(Feature.DEFAULT_PAYLOADS.setWriteType(WriteType.READ_WRITE))
+                                    .addFeature(Feature.TAGS.setWriteType(WriteType.READ_WRITE)),
+                            AccessGroups.TESTING
+                                    .addFeature(Feature.START_TEST_RUN.setWriteType(WriteType.READ_WRITE))
+                                    .addFeature(Feature.TEST_RESULTS.setWriteType(WriteType.READ_WRITE))
+                                    .addFeature(Feature.TEST_ROLES.setWriteType(WriteType.READ_WRITE))
+                                    .addFeature(Feature.USER_CONFIG.setWriteType(WriteType.READ_WRITE))
+                                    .addFeature(Feature.AUTH_TYPE.setWriteType(WriteType.READ_WRITE))
+                                    .addFeature(Feature.ISSUES.setWriteType(WriteType.READ_WRITE)),
+                            AccessGroups.TEST_LIBRARY
+                                    .addFeature(Feature.TEST_EDITOR.setWriteType(WriteType.READ_WRITE))
+                                    .addFeature(Feature.EXTERNAL_TEST_LIBRARY.setWriteType(WriteType.READ_WRITE)),
+                            AccessGroups.SETTINGS
+                                    .addFeature(Feature.INTEGRATIONS.setWriteType(WriteType.READ_WRITE))
+                                    .addFeature(Feature.METRICS.setWriteType(WriteType.READ_WRITE))
+                                    .addFeature(Feature.LOGS.setWriteType(WriteType.READ_WRITE))
+                                    .addFeature(Feature.BILLING.setWriteType(WriteType.READ_WRITE))
+
+                    };
+                case MEMBER:
+                case DEVELOPER:
+                case GUEST:
+            }
+            return null;
+        }
+
+        private static Role[] allowedAccess(Role role) {
+            switch (role) {
+                case ADMIN:
+                    return new Role[]{ADMIN, MEMBER, DEVELOPER, GUEST};
+                case MEMBER:
+                    return new Role[]{MEMBER, DEVELOPER, GUEST};
+                case DEVELOPER:
+                    return new Role[]{DEVELOPER, GUEST};
+                case GUEST:
+                    return new Role[]{};
+            }
+            return null;
+        }
+    }
+    public enum AccessGroups {
+        INVENTORY,
+        TESTING,
+        TEST_LIBRARY,
+        SETTINGS;
+
+        final private Set<Feature> features;
+
+        AccessGroups() {
+            features = new HashSet<>();
+        }
+
+        public AccessGroups setFeatures(Feature[] features) {
+            this.features.addAll(Arrays.asList(features));
+            return this;
+        }
+
+        public AccessGroups addFeature(Feature feature) {
+            this.features.add(feature);
+            return this;
+        }
+    }
+
+    public enum Feature {
+        //Inventory Features
+        API_COLLECTIONS,
+        SENSITIVE_DATA,
+        TRAFFIC_FILTERS,
+        DEFAULT_PAYLOADS,
+        TAGS,
+
+        //Testrun features
+        START_TEST_RUN,
+        TEST_RESULTS,
+        TEST_ROLES,
+        USER_CONFIG,
+        AUTH_TYPE,
+        ISSUES,
+
+        //Test Library features
+        TEST_EDITOR,
+        EXTERNAL_TEST_LIBRARY,
+
+        //Settings features
+        INTEGRATIONS,
+        METRICS,
+        LOGS,
+
+        //Billing Features
+        BILLING;
+
+
+        private WriteType writeType;
+        public Feature setWriteType(WriteType writeType) {
+            this.writeType = writeType;
+            return this;
+        }
+    }
+
+    public enum WriteType {
+        READ,
+        READ_WRITE
     }
 
     public RBAC(int userId, Role role) {

From 34f35489f8fed47e6767c9fc08c4159a9a2b998d Mon Sep 17 00:00:00 2001
From: shivamrawat101192 <shivam@akto.io>
Date: Wed, 12 Jun 2024 11:45:43 +0530
Subject: [PATCH 03/24] rbac initial enums for handling of groups and features

---
 libs/dao/src/main/java/com/akto/dto/RBAC.java | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libs/dao/src/main/java/com/akto/dto/RBAC.java b/libs/dao/src/main/java/com/akto/dto/RBAC.java
index d2c1aadc74..f35cf349aa 100644
--- a/libs/dao/src/main/java/com/akto/dto/RBAC.java
+++ b/libs/dao/src/main/java/com/akto/dto/RBAC.java
@@ -23,13 +23,13 @@ public enum Role {
         GUEST("GUEST");
 
         final String name;
-        final Role[] allowedAccess;//invitation
+        final Role[] roleHierarchy;//invitation
         final AccessGroups[] allowedAccessForRole;
 
 
         Role(String name) {
             this.name = name;
-            this.allowedAccess = Role.allowedAccess(this);
+            this.roleHierarchy = Role.roleHierarchy(this);
             this.allowedAccessForRole = Role.createAccessGroupsForRole(this);
         }
 
@@ -67,7 +67,7 @@ private static AccessGroups[] createAccessGroupsForRole(Role role) {
             return null;
         }
 
-        private static Role[] allowedAccess(Role role) {
+        private static Role[] roleHierarchy(Role role) {
             switch (role) {
                 case ADMIN:
                     return new Role[]{ADMIN, MEMBER, DEVELOPER, GUEST};

From 13f238301708ae104b34c4a367a7c13be92d9b4a Mon Sep 17 00:00:00 2001
From: shivamrawat101192 <shivam@akto.io>
Date: Wed, 12 Jun 2024 12:24:32 +0530
Subject: [PATCH 04/24] rbac initial enums for handling of groups and features

---
 libs/dao/src/main/java/com/akto/dto/RBAC.java | 159 ++++++++++--------
 1 file changed, 93 insertions(+), 66 deletions(-)

diff --git a/libs/dao/src/main/java/com/akto/dto/RBAC.java b/libs/dao/src/main/java/com/akto/dto/RBAC.java
index f35cf349aa..dcd719a7c1 100644
--- a/libs/dao/src/main/java/com/akto/dto/RBAC.java
+++ b/libs/dao/src/main/java/com/akto/dto/RBAC.java
@@ -5,6 +5,8 @@
 
 import java.util.*;
 
+import static com.akto.dto.RBAC.AccessGroups.*;
+
 public class RBAC {
 
     private ObjectId id;
@@ -24,49 +26,66 @@ public enum Role {
 
         final String name;
         final Role[] roleHierarchy;//invitation
-        final AccessGroups[] allowedAccessForRole;
+        final Map<Feature, ReadWriteAccess> featureReadWriteAccessMap;
+        private static final Role[] roles = values();
 
+        public static Role[] getRoles() {
+            return roles;
+        }
 
         Role(String name) {
             this.name = name;
-            this.roleHierarchy = Role.roleHierarchy(this);
-            this.allowedAccessForRole = Role.createAccessGroupsForRole(this);
+            this.roleHierarchy = roleHierarchy(this);
+            this.featureReadWriteAccessMap = createFeatureMap(this);
+        }
+
+        public ReadWriteAccess getReadWriteAccessForFeature(Feature feature) {
+            return this.featureReadWriteAccessMap.get(feature);
         }
 
-        private static AccessGroups[] createAccessGroupsForRole(Role role) {
+        private Map<Feature, ReadWriteAccess> createFeatureMap (Role role) {
+            Map<Feature, ReadWriteAccess> featureReadWriteAccessMap = new HashMap<>();
             switch (role) {
                 case ADMIN:
-                    return new AccessGroups[]{
-                            AccessGroups.INVENTORY
-                                    .addFeature(Feature.API_COLLECTIONS.setWriteType(WriteType.READ_WRITE))
-                                    .addFeature(Feature.SENSITIVE_DATA.setWriteType(WriteType.READ_WRITE))
-                                    .addFeature(Feature.TRAFFIC_FILTERS.setWriteType(WriteType.READ_WRITE))
-                                    .addFeature(Feature.DEFAULT_PAYLOADS.setWriteType(WriteType.READ_WRITE))
-                                    .addFeature(Feature.TAGS.setWriteType(WriteType.READ_WRITE)),
-                            AccessGroups.TESTING
-                                    .addFeature(Feature.START_TEST_RUN.setWriteType(WriteType.READ_WRITE))
-                                    .addFeature(Feature.TEST_RESULTS.setWriteType(WriteType.READ_WRITE))
-                                    .addFeature(Feature.TEST_ROLES.setWriteType(WriteType.READ_WRITE))
-                                    .addFeature(Feature.USER_CONFIG.setWriteType(WriteType.READ_WRITE))
-                                    .addFeature(Feature.AUTH_TYPE.setWriteType(WriteType.READ_WRITE))
-                                    .addFeature(Feature.ISSUES.setWriteType(WriteType.READ_WRITE)),
-                            AccessGroups.TEST_LIBRARY
-                                    .addFeature(Feature.TEST_EDITOR.setWriteType(WriteType.READ_WRITE))
-                                    .addFeature(Feature.EXTERNAL_TEST_LIBRARY.setWriteType(WriteType.READ_WRITE)),
-                            AccessGroups.SETTINGS
-                                    .addFeature(Feature.INTEGRATIONS.setWriteType(WriteType.READ_WRITE))
-                                    .addFeature(Feature.METRICS.setWriteType(WriteType.READ_WRITE))
-                                    .addFeature(Feature.LOGS.setWriteType(WriteType.READ_WRITE))
-                                    .addFeature(Feature.BILLING.setWriteType(WriteType.READ_WRITE))
-
-                    };
+                    for (AccessGroups accessGroup: AccessGroups.getAccessGroups()) {
+                        for (Feature feature: Feature.getFeaturesForAccessGroup(accessGroup)) {
+                            featureReadWriteAccessMap.put(feature, ReadWriteAccess.READ_WRITE);
+                        }
+                    }
                 case MEMBER:
+                    for (AccessGroups accessGroup: AccessGroups.getAccessGroups()) {
+                        if (accessGroup.equals(SETTINGS)) {
+                            for (Feature feature: Feature.getFeaturesForAccessGroup(accessGroup)) {
+                                featureReadWriteAccessMap.put(feature, ReadWriteAccess.READ);
+                            }
+                        } else {
+                            for (Feature feature: Feature.getFeaturesForAccessGroup(accessGroup)) {
+                                featureReadWriteAccessMap.put(feature, ReadWriteAccess.READ_WRITE);
+                            }
+                        }
+                    }
                 case DEVELOPER:
+                    for (AccessGroups accessGroup: AccessGroups.getAccessGroups()) {
+                        if (accessGroup.equals(SETTINGS)) {
+                            for (Feature feature: Feature.getFeaturesForAccessGroup(accessGroup)) {
+                                featureReadWriteAccessMap.put(feature, ReadWriteAccess.READ_WRITE);
+                            }
+                        } else {
+                            for (Feature feature: Feature.getFeaturesForAccessGroup(accessGroup)) {
+                                featureReadWriteAccessMap.put(feature, ReadWriteAccess.READ);
+                            }
+                        }
+                    }
                 case GUEST:
+                    for (AccessGroups accessGroup: AccessGroups.getAccessGroups()) {
+                        for (Feature feature: Feature.getFeaturesForAccessGroup(accessGroup)) {
+                            featureReadWriteAccessMap.put(feature, ReadWriteAccess.READ);
+                        }
+                    }
+                    break;
             }
-            return null;
+            return featureReadWriteAccessMap;
         }
-
         private static Role[] roleHierarchy(Role role) {
             switch (role) {
                 case ADMIN:
@@ -80,67 +99,75 @@ private static Role[] roleHierarchy(Role role) {
             }
             return null;
         }
+
+
     }
+
     public enum AccessGroups {
         INVENTORY,
         TESTING,
         TEST_LIBRARY,
         SETTINGS;
 
-        final private Set<Feature> features;
-
-        AccessGroups() {
-            features = new HashSet<>();
-        }
-
-        public AccessGroups setFeatures(Feature[] features) {
-            this.features.addAll(Arrays.asList(features));
-            return this;
-        }
-
-        public AccessGroups addFeature(Feature feature) {
-            this.features.add(feature);
-            return this;
+        private static final AccessGroups[] accessGroups = values();
+        public static AccessGroups[] getAccessGroups() {
+            return accessGroups;
         }
     }
 
     public enum Feature {
         //Inventory Features
-        API_COLLECTIONS,
-        SENSITIVE_DATA,
-        TRAFFIC_FILTERS,
-        DEFAULT_PAYLOADS,
-        TAGS,
+        API_COLLECTIONS(INVENTORY),
+        SENSITIVE_DATA(INVENTORY),
+        TRAFFIC_FILTERS(INVENTORY),
+        DEFAULT_PAYLOADS(INVENTORY),
+        TAGS(INVENTORY),
 
         //Testrun features
-        START_TEST_RUN,
-        TEST_RESULTS,
-        TEST_ROLES,
-        USER_CONFIG,
-        AUTH_TYPE,
-        ISSUES,
+        START_TEST_RUN(TESTING),
+        TEST_RESULTS(TESTING),
+        TEST_ROLES(TESTING),
+        USER_CONFIG(TESTING),
+        AUTH_TYPE(TESTING),
+        ISSUES(TESTING),
 
         //Test Library features
-        TEST_EDITOR,
-        EXTERNAL_TEST_LIBRARY,
+        TEST_EDITOR(TEST_LIBRARY),
+        EXTERNAL_TEST_LIBRARY(TEST_LIBRARY),
 
         //Settings features
-        INTEGRATIONS,
-        METRICS,
-        LOGS,
+        INTEGRATIONS(SETTINGS),
+        METRICS(SETTINGS),
+        LOGS(SETTINGS),
 
         //Billing Features
-        BILLING;
+        BILLING(SETTINGS);
+
+
+        private final AccessGroups accessGroups;
 
+        Feature(AccessGroups accessGroups) {
+            this.accessGroups = accessGroups;
+        }
+
+        private static final Feature[] features = values();
+
+        public static List<Feature> getFeaturesForAccessGroup(AccessGroups accessGroups) {
+            List<Feature> featureList = new ArrayList<>();
+            for (Feature feature : getFeatures()) {
+                if (feature.accessGroups.equals(accessGroups)) {
+                    featureList.add(feature);
+                }
+            }
+            return featureList;
+        }
 
-        private WriteType writeType;
-        public Feature setWriteType(WriteType writeType) {
-            this.writeType = writeType;
-            return this;
+        public static Feature[] getFeatures() {
+            return features;
         }
     }
 
-    public enum WriteType {
+    public enum ReadWriteAccess {
         READ,
         READ_WRITE
     }

From 4d4a12526ff4cf9e1787d12935f465453eb22495 Mon Sep 17 00:00:00 2001
From: shivamrawat101192 <shivam@akto.io>
Date: Wed, 12 Jun 2024 12:25:41 +0530
Subject: [PATCH 05/24] rbac final enums for hierarchy and featurelist

---
 libs/dao/src/main/java/com/akto/dto/RBAC.java | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libs/dao/src/main/java/com/akto/dto/RBAC.java b/libs/dao/src/main/java/com/akto/dto/RBAC.java
index dcd719a7c1..cb4d2b8d4a 100644
--- a/libs/dao/src/main/java/com/akto/dto/RBAC.java
+++ b/libs/dao/src/main/java/com/akto/dto/RBAC.java
@@ -39,6 +39,9 @@ public static Role[] getRoles() {
             this.featureReadWriteAccessMap = createFeatureMap(this);
         }
 
+        public Role[] getRoleHierarchy () {
+            return this.roleHierarchy;
+        }
         public ReadWriteAccess getReadWriteAccessForFeature(Feature feature) {
             return this.featureReadWriteAccessMap.get(feature);
         }

From b387ab4564636f96fdf3adad7b14b8b6f8bde261 Mon Sep 17 00:00:00 2001
From: Ark2307 <kr.aryan2307@gmail.com>
Date: Wed, 12 Jun 2024 15:37:04 +0530
Subject: [PATCH 06/24] fixed rbac by strategy pattern

---
 libs/dao/src/main/java/com/akto/dto/RBAC.java | 163 ++----------------
 .../com/akto/dto/rbac/AdminRoleStrategy.java  |  31 ++++
 .../akto/dto/rbac/DeveloperRoleStrategy.java  |  27 +++
 .../com/akto/dto/rbac/GuestRoleStrategy.java  |  27 +++
 .../com/akto/dto/rbac/MemberRoleStrategy.java |  27 +++
 .../java/com/akto/dto/rbac/RbacEnums.java     |  60 +++++++
 .../java/com/akto/dto/rbac/RoleStrategy.java  |  11 ++
 7 files changed, 197 insertions(+), 149 deletions(-)
 create mode 100644 libs/dao/src/main/java/com/akto/dto/rbac/AdminRoleStrategy.java
 create mode 100644 libs/dao/src/main/java/com/akto/dto/rbac/DeveloperRoleStrategy.java
 create mode 100644 libs/dao/src/main/java/com/akto/dto/rbac/GuestRoleStrategy.java
 create mode 100644 libs/dao/src/main/java/com/akto/dto/rbac/MemberRoleStrategy.java
 create mode 100644 libs/dao/src/main/java/com/akto/dto/rbac/RbacEnums.java
 create mode 100644 libs/dao/src/main/java/com/akto/dto/rbac/RoleStrategy.java

diff --git a/libs/dao/src/main/java/com/akto/dto/RBAC.java b/libs/dao/src/main/java/com/akto/dto/RBAC.java
index cb4d2b8d4a..28dd1510f5 100644
--- a/libs/dao/src/main/java/com/akto/dto/RBAC.java
+++ b/libs/dao/src/main/java/com/akto/dto/RBAC.java
@@ -3,9 +3,10 @@
 
 import org.bson.types.ObjectId;
 
-import java.util.*;
+import com.akto.dto.rbac.*;
 
-import static com.akto.dto.RBAC.AccessGroups.*;
+import com.akto.dto.rbac.RbacEnums.Feature;
+import com.akto.dto.rbac.RbacEnums.ReadWriteAccess;
 
 public class RBAC {
 
@@ -19,162 +20,26 @@ public class RBAC {
     public static final String ACCOUNT_ID = "accountId";
 
     public enum Role {
-        ADMIN("ADMIN"),
-        MEMBER("SECURITY ENGINEER"),
-        DEVELOPER("DEVELOPER"),
-        GUEST("GUEST");
-
-        final String name;
-        final Role[] roleHierarchy;//invitation
-        final Map<Feature, ReadWriteAccess> featureReadWriteAccessMap;
-        private static final Role[] roles = values();
-
-        public static Role[] getRoles() {
-            return roles;
-        }
+        ADMIN(new AdminRoleStrategy()),
+        MEMBER(new MemberRoleStrategy()),
+        DEVELOPER(new DeveloperRoleStrategy()),
+        GUEST(new GuestRoleStrategy());
 
-        Role(String name) {
-            this.name = name;
-            this.roleHierarchy = roleHierarchy(this);
-            this.featureReadWriteAccessMap = createFeatureMap(this);
-        }
+        private final RoleStrategy roleStrategy;
 
-        public Role[] getRoleHierarchy () {
-            return this.roleHierarchy;
-        }
-        public ReadWriteAccess getReadWriteAccessForFeature(Feature feature) {
-            return this.featureReadWriteAccessMap.get(feature);
-        }
-
-        private Map<Feature, ReadWriteAccess> createFeatureMap (Role role) {
-            Map<Feature, ReadWriteAccess> featureReadWriteAccessMap = new HashMap<>();
-            switch (role) {
-                case ADMIN:
-                    for (AccessGroups accessGroup: AccessGroups.getAccessGroups()) {
-                        for (Feature feature: Feature.getFeaturesForAccessGroup(accessGroup)) {
-                            featureReadWriteAccessMap.put(feature, ReadWriteAccess.READ_WRITE);
-                        }
-                    }
-                case MEMBER:
-                    for (AccessGroups accessGroup: AccessGroups.getAccessGroups()) {
-                        if (accessGroup.equals(SETTINGS)) {
-                            for (Feature feature: Feature.getFeaturesForAccessGroup(accessGroup)) {
-                                featureReadWriteAccessMap.put(feature, ReadWriteAccess.READ);
-                            }
-                        } else {
-                            for (Feature feature: Feature.getFeaturesForAccessGroup(accessGroup)) {
-                                featureReadWriteAccessMap.put(feature, ReadWriteAccess.READ_WRITE);
-                            }
-                        }
-                    }
-                case DEVELOPER:
-                    for (AccessGroups accessGroup: AccessGroups.getAccessGroups()) {
-                        if (accessGroup.equals(SETTINGS)) {
-                            for (Feature feature: Feature.getFeaturesForAccessGroup(accessGroup)) {
-                                featureReadWriteAccessMap.put(feature, ReadWriteAccess.READ_WRITE);
-                            }
-                        } else {
-                            for (Feature feature: Feature.getFeaturesForAccessGroup(accessGroup)) {
-                                featureReadWriteAccessMap.put(feature, ReadWriteAccess.READ);
-                            }
-                        }
-                    }
-                case GUEST:
-                    for (AccessGroups accessGroup: AccessGroups.getAccessGroups()) {
-                        for (Feature feature: Feature.getFeaturesForAccessGroup(accessGroup)) {
-                            featureReadWriteAccessMap.put(feature, ReadWriteAccess.READ);
-                        }
-                    }
-                    break;
-            }
-            return featureReadWriteAccessMap;
-        }
-        private static Role[] roleHierarchy(Role role) {
-            switch (role) {
-                case ADMIN:
-                    return new Role[]{ADMIN, MEMBER, DEVELOPER, GUEST};
-                case MEMBER:
-                    return new Role[]{MEMBER, DEVELOPER, GUEST};
-                case DEVELOPER:
-                    return new Role[]{DEVELOPER, GUEST};
-                case GUEST:
-                    return new Role[]{};
-            }
-            return null;
+        Role(RoleStrategy roleStrategy) {
+            this.roleStrategy = roleStrategy;
         }
 
-
-    }
-
-    public enum AccessGroups {
-        INVENTORY,
-        TESTING,
-        TEST_LIBRARY,
-        SETTINGS;
-
-        private static final AccessGroups[] accessGroups = values();
-        public static AccessGroups[] getAccessGroups() {
-            return accessGroups;
+        public Role[] getRoleHierarchy() {
+            return roleStrategy.getRoleHierarchy();
         }
-    }
-
-    public enum Feature {
-        //Inventory Features
-        API_COLLECTIONS(INVENTORY),
-        SENSITIVE_DATA(INVENTORY),
-        TRAFFIC_FILTERS(INVENTORY),
-        DEFAULT_PAYLOADS(INVENTORY),
-        TAGS(INVENTORY),
-
-        //Testrun features
-        START_TEST_RUN(TESTING),
-        TEST_RESULTS(TESTING),
-        TEST_ROLES(TESTING),
-        USER_CONFIG(TESTING),
-        AUTH_TYPE(TESTING),
-        ISSUES(TESTING),
 
-        //Test Library features
-        TEST_EDITOR(TEST_LIBRARY),
-        EXTERNAL_TEST_LIBRARY(TEST_LIBRARY),
-
-        //Settings features
-        INTEGRATIONS(SETTINGS),
-        METRICS(SETTINGS),
-        LOGS(SETTINGS),
-
-        //Billing Features
-        BILLING(SETTINGS);
-
-
-        private final AccessGroups accessGroups;
-
-        Feature(AccessGroups accessGroups) {
-            this.accessGroups = accessGroups;
-        }
-
-        private static final Feature[] features = values();
-
-        public static List<Feature> getFeaturesForAccessGroup(AccessGroups accessGroups) {
-            List<Feature> featureList = new ArrayList<>();
-            for (Feature feature : getFeatures()) {
-                if (feature.accessGroups.equals(accessGroups)) {
-                    featureList.add(feature);
-                }
-            }
-            return featureList;
-        }
-
-        public static Feature[] getFeatures() {
-            return features;
+        public ReadWriteAccess getReadWriteAccessForFeature(Feature feature) {
+            return roleStrategy.getFeatureAccessMap().getOrDefault(feature, ReadWriteAccess.READ);
         }
     }
 
-    public enum ReadWriteAccess {
-        READ,
-        READ_WRITE
-    }
-
     public RBAC(int userId, Role role) {
         this.userId = userId;
         this.role = role;
diff --git a/libs/dao/src/main/java/com/akto/dto/rbac/AdminRoleStrategy.java b/libs/dao/src/main/java/com/akto/dto/rbac/AdminRoleStrategy.java
new file mode 100644
index 0000000000..08b70810fd
--- /dev/null
+++ b/libs/dao/src/main/java/com/akto/dto/rbac/AdminRoleStrategy.java
@@ -0,0 +1,31 @@
+package com.akto.dto.rbac;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.akto.dto.rbac.RbacEnums.AccessGroups;
+import com.akto.dto.rbac.RbacEnums.Feature;
+import com.akto.dto.rbac.RbacEnums.ReadWriteAccess;
+import com.akto.dto.RBAC.Role;
+
+public class AdminRoleStrategy implements RoleStrategy {
+    @Override
+    public Role[] getRoleHierarchy() {
+        return new Role[]{Role.ADMIN, Role.MEMBER, Role.DEVELOPER, Role.GUEST};
+    }
+
+    @Override
+    public Map<Feature, ReadWriteAccess> getFeatureAccessMap() {
+        return createAccessMap(AccessGroups.getAccessGroups(), ReadWriteAccess.READ_WRITE);
+    }
+
+    private Map<Feature, ReadWriteAccess> createAccessMap(AccessGroups[] groups, ReadWriteAccess access) {
+        Map<Feature, ReadWriteAccess> accessMap = new HashMap<>();
+        for (AccessGroups group : groups) {
+            for (Feature feature : Feature.getFeaturesForAccessGroup(group)) {
+                accessMap.put(feature, access);
+            }
+        }
+        return accessMap;
+    }
+}
\ No newline at end of file
diff --git a/libs/dao/src/main/java/com/akto/dto/rbac/DeveloperRoleStrategy.java b/libs/dao/src/main/java/com/akto/dto/rbac/DeveloperRoleStrategy.java
new file mode 100644
index 0000000000..703ea95842
--- /dev/null
+++ b/libs/dao/src/main/java/com/akto/dto/rbac/DeveloperRoleStrategy.java
@@ -0,0 +1,27 @@
+package com.akto.dto.rbac;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.akto.dto.rbac.RbacEnums.AccessGroups;
+import com.akto.dto.rbac.RbacEnums.Feature;
+import com.akto.dto.rbac.RbacEnums.ReadWriteAccess;
+import com.akto.dto.RBAC.Role;
+
+public class DeveloperRoleStrategy implements RoleStrategy{
+    @Override
+    public Role[] getRoleHierarchy() {
+        return new Role[]{Role.DEVELOPER, Role.GUEST};
+    }
+
+    @Override
+    public Map<Feature, ReadWriteAccess> getFeatureAccessMap() {
+        Map<Feature, ReadWriteAccess> accessMap = new HashMap<>();
+        for (AccessGroups group : AccessGroups.getAccessGroups()) {
+            ReadWriteAccess access = group == AccessGroups.SETTINGS ? ReadWriteAccess.READ_WRITE : ReadWriteAccess.READ;
+            for (Feature feature : Feature.getFeaturesForAccessGroup(group)) {
+                accessMap.put(feature, access);
+            }
+        }
+        return accessMap;
+    }
+}
diff --git a/libs/dao/src/main/java/com/akto/dto/rbac/GuestRoleStrategy.java b/libs/dao/src/main/java/com/akto/dto/rbac/GuestRoleStrategy.java
new file mode 100644
index 0000000000..6314712684
--- /dev/null
+++ b/libs/dao/src/main/java/com/akto/dto/rbac/GuestRoleStrategy.java
@@ -0,0 +1,27 @@
+package com.akto.dto.rbac;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.akto.dto.rbac.RbacEnums.AccessGroups;
+import com.akto.dto.rbac.RbacEnums.Feature;
+import com.akto.dto.rbac.RbacEnums.ReadWriteAccess;
+import com.akto.dto.RBAC.Role;
+
+public class GuestRoleStrategy implements RoleStrategy{
+    @Override
+    public Role[] getRoleHierarchy() {
+        return new Role[]{Role.GUEST};
+    }
+
+    @Override
+    public Map<Feature, ReadWriteAccess> getFeatureAccessMap() {
+        Map<Feature, ReadWriteAccess> accessMap = new HashMap<>();
+        for (AccessGroups group : AccessGroups.getAccessGroups()) {
+            ReadWriteAccess access = ReadWriteAccess.READ ;
+            for (Feature feature : Feature.getFeaturesForAccessGroup(group)) {
+                accessMap.put(feature, access);
+            }
+        }
+        return accessMap;
+    }
+}
diff --git a/libs/dao/src/main/java/com/akto/dto/rbac/MemberRoleStrategy.java b/libs/dao/src/main/java/com/akto/dto/rbac/MemberRoleStrategy.java
new file mode 100644
index 0000000000..29ba4d7628
--- /dev/null
+++ b/libs/dao/src/main/java/com/akto/dto/rbac/MemberRoleStrategy.java
@@ -0,0 +1,27 @@
+package com.akto.dto.rbac;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.akto.dto.rbac.RbacEnums.AccessGroups;
+import com.akto.dto.rbac.RbacEnums.Feature;
+import com.akto.dto.rbac.RbacEnums.ReadWriteAccess;
+import com.akto.dto.RBAC.Role;
+
+public class MemberRoleStrategy implements RoleStrategy{
+    @Override
+    public Role[] getRoleHierarchy() {
+        return new Role[]{Role.MEMBER, Role.DEVELOPER, Role.GUEST};
+    }
+
+    @Override
+    public Map<Feature, ReadWriteAccess> getFeatureAccessMap() {
+        Map<Feature, ReadWriteAccess> accessMap = new HashMap<>();
+        for (AccessGroups group : AccessGroups.getAccessGroups()) {
+            ReadWriteAccess access = group == AccessGroups.SETTINGS ? ReadWriteAccess.READ : ReadWriteAccess.READ_WRITE;
+            for (Feature feature : Feature.getFeaturesForAccessGroup(group)) {
+                accessMap.put(feature, access);
+            }
+        }
+        return accessMap;
+    }
+}
diff --git a/libs/dao/src/main/java/com/akto/dto/rbac/RbacEnums.java b/libs/dao/src/main/java/com/akto/dto/rbac/RbacEnums.java
new file mode 100644
index 0000000000..c0c8c7f2a4
--- /dev/null
+++ b/libs/dao/src/main/java/com/akto/dto/rbac/RbacEnums.java
@@ -0,0 +1,60 @@
+package com.akto.dto.rbac;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class RbacEnums {
+
+    public enum AccessGroups {
+        INVENTORY,
+        TESTING,
+        TEST_LIBRARY,
+        SETTINGS;
+    
+        public static AccessGroups[] getAccessGroups() {
+            return values();
+        }
+    }
+
+    public enum Feature {
+        API_COLLECTIONS(AccessGroups.INVENTORY),
+        SENSITIVE_DATA(AccessGroups.INVENTORY),
+        TRAFFIC_FILTERS(AccessGroups.INVENTORY),
+        DEFAULT_PAYLOADS(AccessGroups.INVENTORY),
+        TAGS(AccessGroups.INVENTORY),
+        START_TEST_RUN(AccessGroups.TESTING),
+        TEST_RESULTS(AccessGroups.TESTING),
+        TEST_ROLES(AccessGroups.TESTING),
+        USER_CONFIG(AccessGroups.TESTING),
+        AUTH_TYPE(AccessGroups.TESTING),
+        ISSUES(AccessGroups.TESTING),
+        TEST_EDITOR(AccessGroups.TEST_LIBRARY),
+        EXTERNAL_TEST_LIBRARY(AccessGroups.TEST_LIBRARY),
+        INTEGRATIONS(AccessGroups.SETTINGS),
+        METRICS(AccessGroups.SETTINGS),
+        LOGS(AccessGroups.SETTINGS),
+        BILLING(AccessGroups.SETTINGS);
+
+        private final AccessGroups accessGroup;
+
+        Feature(AccessGroups accessGroup) {
+            this.accessGroup = accessGroup;
+        }
+
+        public AccessGroups getAccessGroup() {
+            return accessGroup;
+        }
+
+        public static List<Feature> getFeaturesForAccessGroup(AccessGroups accessGroup) {
+            return Arrays.stream(values())
+                    .filter(feature -> feature.getAccessGroup() == accessGroup)
+                    .collect(Collectors.toList());
+        }
+    }
+
+    public enum ReadWriteAccess {
+        READ,
+        READ_WRITE
+    }
+}
diff --git a/libs/dao/src/main/java/com/akto/dto/rbac/RoleStrategy.java b/libs/dao/src/main/java/com/akto/dto/rbac/RoleStrategy.java
new file mode 100644
index 0000000000..c24a68e0ad
--- /dev/null
+++ b/libs/dao/src/main/java/com/akto/dto/rbac/RoleStrategy.java
@@ -0,0 +1,11 @@
+package com.akto.dto.rbac;
+
+import java.util.Map;
+import com.akto.dto.RBAC.Role;
+import com.akto.dto.rbac.RbacEnums.Feature;
+import com.akto.dto.rbac.RbacEnums.ReadWriteAccess;
+
+public interface RoleStrategy {
+    Role[] getRoleHierarchy();
+    Map<Feature, ReadWriteAccess> getFeatureAccessMap();
+}
\ No newline at end of file

From 69df4b0c2486165f0e4d65e113008d85ad13508a Mon Sep 17 00:00:00 2001
From: Ark2307 <kr.aryan2307@gmail.com>
Date: Thu, 13 Jun 2024 11:23:05 +0530
Subject: [PATCH 07/24] added support in interceptor

---
 .../interceptor/RoleAccessInterceptor.java    | 51 +++++++++----------
 .../com/akto/interceptor/RoleHierarchy.java   | 26 ----------
 apps/dashboard/src/main/resources/struts.xml  |  4 ++
 3 files changed, 28 insertions(+), 53 deletions(-)
 delete mode 100644 apps/dashboard/src/main/java/com/akto/interceptor/RoleHierarchy.java

diff --git a/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java b/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java
index 7ca2d0edf0..b714c7827e 100644
--- a/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java
+++ b/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java
@@ -2,48 +2,44 @@
 
 import com.akto.dao.RBACDao;
 import com.akto.dto.User;
+import com.akto.dto.RBAC.Role;
+import com.akto.dto.rbac.RbacEnums.Feature;
+import com.akto.dto.rbac.RbacEnums.ReadWriteAccess;
 import com.akto.log.LoggerMaker;
-import com.akto.util.DashboardMode;
 import com.mongodb.client.model.Filters;
 import com.opensymphony.xwork2.ActionInvocation;
 import com.opensymphony.xwork2.ActionSupport;
 import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
 
-import java.util.Arrays;
-import java.util.List;
 import java.util.Map;
-import java.util.stream.Collectors;
 
 public class RoleAccessInterceptor extends AbstractInterceptor {
 
     private static final LoggerMaker loggerMaker = new LoggerMaker(RoleAccessInterceptor.class, LoggerMaker.LogDb.DASHBOARD);
 
-    String rolesList;
+    String featureLabel;
+    String accessType;
+
+    public void setFeatureLabel(String featureLabel) {
+        this.featureLabel = featureLabel;
+    }
+
+    public void setAccessType(String accessType) {
+        this.accessType = accessType;
+    }
 
     public final static String FORBIDDEN = "FORBIDDEN";
     private final static String USER_ID = "userId";
     private final static String USER = "user";
 
-    public void setRolesList(String rolesList) {
-        this.rolesList = rolesList;
-    }
 
     @Override
     public String intercept(ActionInvocation invocation) throws Exception {
         try {
-            if(!DashboardMode.isMetered()) {
-                return invocation.invoke();
+            if(featureLabel == null) {
+                throw new Exception("Feature list is null or empty");
             }
 
-            if(rolesList == null || rolesList.trim().isEmpty()) {
-                throw new Exception("Roles list is null or empty");
-            }
-
-            List<String> roles = Arrays.stream(rolesList.split(" "))
-                                        .map(String::trim)
-                                        .map(String::toUpperCase)
-                                        .collect(Collectors.toList());
-
             Map<String, Object> session = invocation.getInvocationContext().getSession();
             User user = (User) session.get(USER);
 
@@ -59,16 +55,17 @@ public String intercept(ActionInvocation invocation) throws Exception {
                 throw new Exception("User role not found");
             }
 
-            boolean hasRequiredRole = false;
+            Role userRoleType = Role.valueOf(userRole.toUpperCase());
+            Feature featureType = Feature.valueOf(this.featureLabel.toUpperCase());
 
-            for(String requiredRole : roles) {
-                if (RoleHierarchy.hasRole(userRole, requiredRole)) {
-                    hasRequiredRole = true;
-                    break;
-                }
-            }
+            ReadWriteAccess accessGiven = userRoleType.getReadWriteAccessForFeature(featureType);
+            boolean hasRequiredAccess = false;
 
-            if(!hasRequiredRole) {
+            if(accessGiven.toString().equalsIgnoreCase(ReadWriteAccess.READ_WRITE.toString()) || accessGiven.toString().equalsIgnoreCase(this.accessType)){
+                hasRequiredAccess = true;
+            }
+            
+            if(!hasRequiredAccess) {
                 ((ActionSupport) invocation.getAction()).addActionError("The role '" + userRole + "' does not have access.");
                 return FORBIDDEN;
             }
diff --git a/apps/dashboard/src/main/java/com/akto/interceptor/RoleHierarchy.java b/apps/dashboard/src/main/java/com/akto/interceptor/RoleHierarchy.java
deleted file mode 100644
index 9f39ae77c2..0000000000
--- a/apps/dashboard/src/main/java/com/akto/interceptor/RoleHierarchy.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.akto.interceptor;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class RoleHierarchy {
-    private static final Map<String, String[]> hierarchy = new HashMap<>();
-
-    static {
-        hierarchy.put("ADMIN", new String[]{"ADMIN", "MEMBER"});
-        hierarchy.put("MEMBER", new String[]{"MEMBER"});
-    }
-
-    public static boolean hasRole(String userRole, String requiredRole) {
-        String[] roles = hierarchy.get(userRole);
-        if (roles == null) {
-            return false;
-        }
-        for (String role : roles) {
-            if (role.equalsIgnoreCase(requiredRole)) {
-                return true;
-            }
-        }
-        return false;
-    }
-}
diff --git a/apps/dashboard/src/main/resources/struts.xml b/apps/dashboard/src/main/resources/struts.xml
index b6c8560290..519571962a 100644
--- a/apps/dashboard/src/main/resources/struts.xml
+++ b/apps/dashboard/src/main/resources/struts.xml
@@ -949,6 +949,10 @@
         <action name="api/getAllCollections" class="com.akto.action.ApiCollectionsAction" method="fetchAllCollections">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="httpheader">

From 267f5d5b1ba5bb441392fa57b64abf9b98315c73 Mon Sep 17 00:00:00 2001
From: Ark2307 <kr.aryan2307@gmail.com>
Date: Thu, 13 Jun 2024 16:48:52 +0530
Subject: [PATCH 08/24] added userRole in login.jsp and sample api restriction

---
 .../java/com/akto/action/ProfileAction.java   |  8 +++++++-
 apps/dashboard/src/main/resources/struts.xml  |  9 +++++++++
 apps/dashboard/web/pages/login.jsp            |  1 +
 .../src/main/java/com/akto/dao/RBACDao.java   | 19 +++++++++++++++++++
 4 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/apps/dashboard/src/main/java/com/akto/action/ProfileAction.java b/apps/dashboard/src/main/java/com/akto/action/ProfileAction.java
index 2c0b142654..bbc2fc2ebb 100644
--- a/apps/dashboard/src/main/java/com/akto/action/ProfileAction.java
+++ b/apps/dashboard/src/main/java/com/akto/action/ProfileAction.java
@@ -5,12 +5,14 @@
 import com.akto.dao.AccountSettingsDao;
 import com.akto.dao.AccountsDao;
 import com.akto.dao.JiraIntegrationDao;
+import com.akto.dao.RBACDao;
 import com.akto.dao.UsersDao;
 import com.akto.dao.billing.OrganizationsDao;
 import com.akto.dao.context.Context;
 import com.akto.dto.Account;
 import com.akto.dto.AccountSettings;
 import com.akto.dto.JiraIntegration;
+import com.akto.dto.RBAC;
 import com.akto.dto.User;
 import com.akto.dto.UserAccountEntry;
 import com.akto.dto.ApiToken.Utility;
@@ -111,6 +113,9 @@ public static void executeMeta1(Utility utility, User user, HttpServletRequest r
         String dashboardVersion = accountSettings.getDashboardVersion();
         String[] versions = dashboardVersion.split(" - ");
         User userFromDB = UsersDao.instance.findOne(Filters.eq(Constants.ID, user.getId()));
+        RBAC userRbac = RBACDao.instance.findOne(
+            Filters.eq(RBAC.USER_ID, user.getId())
+        );
 
         boolean jiraIntegrated = false;
         try {
@@ -131,7 +136,8 @@ public static void executeMeta1(Utility utility, User user, HttpServletRequest r
                 .append("cloudType", Utils.getCloudType())
                 .append("accountName", accountName)
                 .append("aktoUIMode", userFromDB.getAktoUIMode().name())
-                .append("jiraIntegrated", jiraIntegrated);;
+                .append("jiraIntegrated", jiraIntegrated)
+                .append("userRole", userRbac.getRole().toString().toUpperCase());
 
         if (DashboardMode.isOnPremDeployment()) {
             userDetails.append("userHash", Intercom.getUserHash(user.getLogin()));
diff --git a/apps/dashboard/src/main/resources/struts.xml b/apps/dashboard/src/main/resources/struts.xml
index 519571962a..6c64897337 100644
--- a/apps/dashboard/src/main/resources/struts.xml
+++ b/apps/dashboard/src/main/resources/struts.xml
@@ -1312,6 +1312,15 @@
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">AKTO_EXTERNAL_API CI_CD_INTEGRATION</param>
             </interceptor-ref>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="httpheader">
diff --git a/apps/dashboard/web/pages/login.jsp b/apps/dashboard/web/pages/login.jsp
index fc67b9db70..47e05522db 100644
--- a/apps/dashboard/web/pages/login.jsp
+++ b/apps/dashboard/web/pages/login.jsp
@@ -67,6 +67,7 @@
                     window.STIGG_CUSTOMER_TOKEN='${requestScope.stiggCustomerToken}'
                     window.STIGG_CLIENT_KEY='${requestScope.stiggClientKey}'
                     window.JIRA_INTEGRATED ='${requestScope.jiraIntegrated}'
+                    window.USER_ROLE ='${requestScope.userRole}'
 
                     window.STIGG_IS_OVERAGE='${requestScope.stiggIsOverage}'
                     window.USAGE_PAUSED=JSON.parse('${requestScope.usagePaused}' || '{}');
diff --git a/libs/dao/src/main/java/com/akto/dao/RBACDao.java b/libs/dao/src/main/java/com/akto/dao/RBACDao.java
index 394410d6c7..318ec61f20 100644
--- a/libs/dao/src/main/java/com/akto/dao/RBACDao.java
+++ b/libs/dao/src/main/java/com/akto/dao/RBACDao.java
@@ -1,12 +1,31 @@
 package com.akto.dao;
 
 
+import com.akto.dao.context.Context;
 import com.akto.dto.RBAC;
 import com.mongodb.client.model.Filters;
 
 public class RBACDao extends CommonContextDao<RBAC> {
     public static final RBACDao instance = new RBACDao();
 
+    public void createIndicesIfAbsent() {
+
+        boolean exists = false;
+        for (String col: clients[0].getDatabase(Context.accountId.get()+"").listCollectionNames()){
+            if (getCollName().equalsIgnoreCase(col)){
+                exists = true;
+                break;
+            }
+        };
+
+        if (!exists) {
+            clients[0].getDatabase(Context.accountId.get()+"").createCollection(getCollName());
+        }
+
+        String[] fieldNames = {RBAC.USER_ID};
+        MCollection.createIndexIfAbsent(getDBName(), getCollName(), fieldNames, true);
+    }
+
     public boolean isAdmin(int userId, int accountId) {
         RBAC rbac = RBACDao.instance.findOne(
                 Filters.or(Filters.and(

From 2866f380d36d2c29fe645acfa983a64b4ca61fa8 Mon Sep 17 00:00:00 2001
From: Ark2307 <kr.aryan2307@gmail.com>
Date: Tue, 18 Jun 2024 08:58:43 +0530
Subject: [PATCH 09/24] added support for rbac in struts

---
 .../interceptor/RoleAccessInterceptor.java    |    2 +-
 apps/dashboard/src/main/resources/struts.xml  | 2592 ++++++++++++++++-
 .../pages/settings/users/InviteUserModal.jsx  |   25 +-
 .../dashboard/pages/settings/users/Users.jsx  |  144 +-
 .../akto/dto/rbac/DeveloperRoleStrategy.java  |    5 +-
 .../com/akto/dto/rbac/MemberRoleStrategy.java |    5 +-
 .../java/com/akto/dto/rbac/RbacEnums.java     |   12 +-
 7 files changed, 2659 insertions(+), 126 deletions(-)

diff --git a/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java b/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java
index b714c7827e..e3fd5fea89 100644
--- a/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java
+++ b/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java
@@ -61,7 +61,7 @@ public String intercept(ActionInvocation invocation) throws Exception {
             ReadWriteAccess accessGiven = userRoleType.getReadWriteAccessForFeature(featureType);
             boolean hasRequiredAccess = false;
 
-            if(accessGiven.toString().equalsIgnoreCase(ReadWriteAccess.READ_WRITE.toString()) || accessGiven.toString().equalsIgnoreCase(this.accessType)){
+            if(this.accessType.equalsIgnoreCase(ReadWriteAccess.READ.toString()) || this.accessType.equalsIgnoreCase(accessGiven.toString())){
                 hasRequiredAccess = true;
             }
             
diff --git a/apps/dashboard/src/main/resources/struts.xml b/apps/dashboard/src/main/resources/struts.xml
index 6c64897337..8abb438f6f 100644
--- a/apps/dashboard/src/main/resources/struts.xml
+++ b/apps/dashboard/src/main/resources/struts.xml
@@ -125,6 +125,15 @@
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">ACTIVE_ACCOUNTS</param>
             </interceptor-ref>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="httpheader">
                 <param name="status">401</param>
@@ -139,6 +148,15 @@
         <action name="api/goToAccount" class="com.akto.action.AccountAction" method="goToAccount">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
                 <param name="root">newAccountId</param>
             </result>
@@ -150,6 +168,15 @@
         <action name="api/googleConfig" class="com.akto.action.tpi.GoogleAuthAction" method="retrieveGoogleConfig">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
                 <param name="root">googleConfigResult</param>
             </result>
@@ -161,6 +188,15 @@
         <action name="api/sendGoogleAuthCodeToServer" class="com.akto.action.tpi.GoogleAuthAction" method="sendGoogleAuthCodeToServer">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="httpheader">
                 <param name="status">401</param>
@@ -170,6 +206,15 @@
         <action name="api/getDriveNames" class="com.akto.action.tpi.GoogleAuthAction" method="fetchDriveNames">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
                 <param name="root">driveNamesToThirdPartyId</param>
             <result name="ERROR" type="httpheader">
@@ -180,6 +225,15 @@
         <action name="api/getSpreadsheets" class="com.akto.action.tpi.GoogleAuthAction" method="fetchSpreadsheets">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="httpheader">
                 <param name="status">401</param>
@@ -189,6 +243,15 @@
         <action name="api/fetchWorksheetsFromSheet" class="com.akto.action.tpi.GoogleAuthAction" method="fetchWorksheetsFromSheet">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="httpheader">
                 <param name="status">401</param>
@@ -198,6 +261,15 @@
         <action name="api/fetchDataFromWorksheet" class="com.akto.action.tpi.GoogleAuthAction" method="fetchDataFromWorksheet">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="httpheader">
                 <param name="status">401</param>
@@ -209,6 +281,15 @@
         <action name="api/getTeamData" class="com.akto.action.TeamAction" method="fetchTeamData">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INVITE_MEMBERS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="httpheader">
                 <param name="status">401</param>
@@ -219,9 +300,9 @@
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
             <interceptor-ref name="roleAccessInterceptor">
-                <param name="rolesList">ADMIN</param>
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
             </interceptor-ref>
-
             <result name="FORBIDDEN" type="json">
                 <param name="statusCode">403</param>
                 <param name="ignoreHierarchy">false</param>
@@ -237,9 +318,9 @@
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
             <interceptor-ref name="roleAccessInterceptor">
-                <param name="rolesList">ADMIN</param>
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
             </interceptor-ref>
-
             <result name="FORBIDDEN" type="json">
                 <param name="statusCode">403</param>
                 <param name="ignoreHierarchy">false</param>
@@ -256,6 +337,15 @@
         <action name="signup-email" class="com.akto.action.SignupAction" method="registerViaEmail">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_ACTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="root">code</param>
@@ -265,6 +355,15 @@
         <action name="signup-google" class="com.akto.action.SignupAction" method="registerViaGoogle">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_ACTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="root">code</param>
@@ -275,6 +374,15 @@
         <action name="signup-github" class="com.akto.action.SignupAction" method="registerViaGithub">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_ACTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="root">code</param>
@@ -284,6 +392,15 @@
         <action name="authorization-code/callback" class="com.akto.action.SignupAction" method="registerViaOkta">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_ACTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="root">code</param>
@@ -293,6 +410,15 @@
         <action name="signup-azure-request" class="com.akto.action.SignupAction" method="sendRequestToAzure">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="root">code</param>
@@ -302,6 +428,15 @@
         <action name="signup-azure-saml" class="com.akto.action.SignupAction" method="registerViaAzure">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_ACTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="root">code</param>
@@ -315,7 +450,8 @@
                 <param name="featureLabel">AKTO_SSO</param>
             </interceptor-ref>
             <interceptor-ref name="roleAccessInterceptor">
-                <param name="rolesList">ADMIN</param>
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
             </interceptor-ref>
 
             <result name="FORBIDDEN" type="json">
@@ -343,7 +479,8 @@
                 <param name="featureLabel">AKTO_SSO</param>
             </interceptor-ref>
             <interceptor-ref name="roleAccessInterceptor">
-                <param name="rolesList">ADMIN</param>
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
             </interceptor-ref>
 
             <result name="FORBIDDEN" type="json">
@@ -367,6 +504,16 @@
         <action name="api/fetchGithubSso" class="com.akto.action.user.GithubSsoAction">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -382,7 +529,8 @@
                 <param name="featureLabel">AKTO_SSO</param>
             </interceptor-ref>
             <interceptor-ref name="roleAccessInterceptor">
-                <param name="rolesList">ADMIN</param>
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
             </interceptor-ref>
 
             <result name="FORBIDDEN" type="json">
@@ -410,7 +558,8 @@
                 <param name="featureLabel">AKTO_SSO</param>
             </interceptor-ref>
             <interceptor-ref name="roleAccessInterceptor">
-                <param name="rolesList">ADMIN</param>
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
             </interceptor-ref>
 
             <result name="FORBIDDEN" type="json">
@@ -434,6 +583,16 @@
          <action name="api/fetchOktaSso" class="com.akto.action.user.OktaSsoAction">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -449,7 +608,8 @@
                 <param name="featureLabel">AKTO_SSO</param>
             </interceptor-ref>
             <interceptor-ref name="roleAccessInterceptor">
-                <param name="rolesList">ADMIN</param>
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
             </interceptor-ref>
 
             <result name="FORBIDDEN" type="json">
@@ -477,7 +637,8 @@
                 <param name="featureLabel">AKTO_SSO</param>
             </interceptor-ref>
             <interceptor-ref name="roleAccessInterceptor">
-                <param name="rolesList">ADMIN</param>
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
             </interceptor-ref>
 
             <result name="FORBIDDEN" type="json">
@@ -501,6 +662,16 @@
          <action name="api/fetchAzureSso" class="com.akto.action.user.AzureSsoAction">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -512,6 +683,16 @@
         <action name="api/fetchGithubAppId" class="com.akto.action.user.GithubSsoAction" method="fetchGithubAppId">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -524,7 +705,8 @@
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
             <interceptor-ref name="roleAccessInterceptor">
-                <param name="rolesList">ADMIN</param>
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
             </interceptor-ref>
 
             <result name="FORBIDDEN" type="json">
@@ -544,7 +726,8 @@
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
             <interceptor-ref name="roleAccessInterceptor">
-                <param name="rolesList">ADMIN</param>
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
             </interceptor-ref>
 
             <result name="FORBIDDEN" type="json">
@@ -563,6 +746,10 @@
         <action name="api/getAPICatalog" class="com.akto.action.APICatalogAction" method="getAPICatalog">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_ACTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
             <result name="SUCCESS"   type="json">
                 <param name="root">apiCatalogData</param>
             </result>
@@ -577,6 +764,16 @@
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
             <interceptor-ref name="collectionInterceptor"/>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json">
                 <param name="root">response</param>
             </result>
@@ -595,6 +792,16 @@
         <action name="api/loadRecentEndpoints" class="com.akto.action.observe.InventoryAction" method="loadRecentEndpoints">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json">
                 <param name="root">response</param>
             </result>
@@ -606,6 +813,16 @@
         <action name="api/fetchNewParametersTrend" class="com.akto.action.observe.InventoryAction" method="fetchNewParametersTrend">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json">
                 <param name="root">response</param>
             </result>
@@ -617,6 +834,16 @@
         <action name="api/fetchCollectionWiseApiEndpoints" class="com.akto.action.observe.InventoryAction" method="fetchCollectionWiseApiEndpoints">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="collectionInterceptor"/>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="httpheader">
@@ -632,6 +859,16 @@
         <action name="api/loadParamsOfEndpoint" class="com.akto.action.observe.InventoryAction" method="loadParamsOfEndpoint">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="collectionInterceptor"/>
             <result name="SUCCESS"   type="json">
                 <param name="root">response</param>
@@ -650,6 +887,16 @@
         <action name="api/loadSensitiveParameters" class="com.akto.action.observe.InventoryAction" method="loadSensitiveParameters">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">SENSITIVE_DATA</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="collectionInterceptor"/>
             <result name="SUCCESS"   type="json">
                 <param name="root">response</param>
@@ -667,6 +914,16 @@
         <action name="api/fetchSensitiveParamsForEndpoints" class="com.akto.action.observe.InventoryAction" method="fetchSensitiveParamsForEndpoints">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">SENSITIVE_DATA</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json">
                 <param name="root">response</param>
             </result>
@@ -679,6 +936,16 @@
         <action name="api/fetchAllUrlsAndMethods" class="com.akto.action.observe.InventoryAction" method="fetchAllUrlsAndMethods">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="collectionInterceptor"/>
             <result name="SUCCESS"   type="json">
                 <param name="root">response</param>
@@ -694,19 +961,39 @@
         </action>
 
         <action name="api/setFalsePositives" class="com.akto.action.IgnoreFalsePositivesAction" method="setFalsePositivesInSensitiveData">
-        <interceptor-ref name="json"/>
-        <interceptor-ref name="defaultStack" />
-        <result name="SUCCESS"  type="json">
-            <param name="root">response</param>
-        </result>
-        <result name="ERROR" type="httpheader">
-            <param name="status">401</param>
-        </result>
-    </action>
-
+            <interceptor-ref name="json"/>
+            <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ISSUES</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
+            <result name="SUCCESS"  type="json">
+                <param name="root">response</param>
+            </result>
+            <result name="ERROR" type="httpheader">
+                <param name="status">401</param>
+            </result>
+        </action>
+
     <action name="api/inviteUsers" class="com.akto.action.InviteUserAction">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="json">
@@ -730,6 +1017,16 @@
         <action name="api/addSensitiveField" class="com.akto.action.SensitiveFieldAction">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">SENSITIVE_DATA</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
                 <param name="root">ret</param>
             </result>
@@ -742,6 +1039,16 @@
         <action name="api/bulkMarkSensitive" class="com.akto.action.SensitiveFieldAction" method="bulkMarkSensitive">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">SENSITIVE_DATA</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
                 <param name="root">ret</param>
             </result>
@@ -754,6 +1061,16 @@
         <action name="api/listAllSensitiveFields" class="com.akto.action.SensitiveFieldAction" method="listAllSensitiveFields">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">SENSITIVE_DATA</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
                 <param name="root">ret</param>
             </result>
@@ -762,21 +1079,19 @@
             </result>
         </action>
 
-        <action name="api/inviteUsers" class="com.akto.action.InviteUserAction">
+        <action name="api/fetchAccessMatrixTaskInfos" class="com.akto.action.testing.AccessMatrixTaskAction" method="fetchAccessMatrixTaskInfos">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
-            <result name="SUCCESS"  type="json">
-            </result>
-            <result name="ERROR" type="json">
-                <param name="statusCode">422</param>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_CONFIG</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
                 <param name="ignoreHierarchy">false</param>
                 <param name="includeProperties">^actionErrors.*</param>
             </result>
-        </action>
-
-        <action name="api/fetchAccessMatrixTaskInfos" class="com.akto.action.testing.AccessMatrixTaskAction" method="fetchAccessMatrixTaskInfos">
-            <interceptor-ref name="json"/>
-            <interceptor-ref name="defaultStack" />
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -788,6 +1103,16 @@
         <action name="api/analyzeApiSamples" class="com.akto.action.testing.AccessMatrixTaskAction" method="analyzeApiSamples">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_CONFIG</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -799,6 +1124,16 @@
         <action name="api/fetchAccessMatrixUrlToRoles" class="com.akto.action.testing.AccessMatrixTaskAction" method="fetchAccessMatrixUrlToRoles">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_ROLES</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -810,6 +1145,16 @@
         <action name="api/updateAccessMatrixTask" class="com.akto.action.testing.AccessMatrixTaskAction" method="updateAccessMatrixTask">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_CONFIG</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -821,6 +1166,16 @@
         <action name="api/createMultipleAccessMatrixTasks" class="com.akto.action.testing.AccessMatrixTaskAction" method="createMultipleAccessMatrixTasks">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_CONFIG</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -831,6 +1186,16 @@
         <action name="api/deleteAccessMatrix" class="com.akto.action.testing.AccessMatrixTaskAction" method="deleteAccessMatrix">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_CONFIG</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -842,6 +1207,16 @@
         <action name="api/deleteAccessMatrixTask" class="com.akto.action.testing.AccessMatrixTaskAction" method="deleteAccessMatrixTask">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_CONFIG</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -853,6 +1228,16 @@
         <action name="api/generateOpenApiFile" class="com.akto.action.OpenApiAction">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="httpheader">
@@ -863,6 +1248,16 @@
         <action name="api/deactivateCollections" class="com.akto.action.ApiCollectionsAction" method="deactivateCollections">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -877,6 +1272,16 @@
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">ACTIVE_ENDPOINTS</param>
             </interceptor-ref>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="json">
@@ -894,6 +1299,16 @@
         <action name="api/activateCollections" class="com.akto.action.ApiCollectionsAction" method="activateCollections">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -909,6 +1324,16 @@
         <action name="api/fetchSwaggerImportLogs" class="com.akto.action.OpenApiAction" method="fetchImportLogs">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">ACTIVE_ENDPOINTS</param>
             </interceptor-ref>
@@ -929,6 +1354,16 @@
         <action name="api/importSwaggerLogs" class="com.akto.action.OpenApiAction" method="importFile">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">ACTIVE_ENDPOINTS</param>
             </interceptor-ref>
@@ -953,6 +1388,11 @@
                 <param name="featureLabel">API_COLLECTIONS</param>
                 <param name="accessType">READ</param>
             </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="httpheader">
@@ -962,6 +1402,15 @@
         <action name="api/getSensitiveInfoForCollections" class="com.akto.action.ApiCollectionsAction" method="fetchSensitiveInfoInCollections">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="httpheader">
@@ -972,6 +1421,15 @@
         <action name="api/getCoverageInfoForCollections" class="com.akto.action.ApiCollectionsAction" method="fetchCoverageInfoInCollections">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
                 <param name="root">testedEndpointsMaps</param>
             </result>
@@ -983,6 +1441,15 @@
         <action name="api/getSeverityInfoForCollections" class="com.akto.action.ApiCollectionsAction" method="fetchSeverityInfoInCollections">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
                 <param name="root">severityInfo</param>
             </result>
@@ -994,6 +1461,15 @@
         <action name="api/getLastSeenTrafficInfoForCollections" class="com.akto.action.ApiCollectionsAction" method="fetchLastSeenInfoInCollections">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
                 <param name="root">lastTrafficSeenMap</param>
             </result>
@@ -1005,6 +1481,15 @@
         <action name="api/getRiskScoreInfo" class="com.akto.action.ApiCollectionsAction" method="fetchRiskScoreInfo">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="httpheader">
@@ -1015,6 +1500,15 @@
         <action name="api/getLastCalculatedInfo" class="com.akto.action.ApiCollectionsAction" method="fetchTimersInfo">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
                 <param name="root">timerInfo</param>
             </result>
@@ -1026,6 +1520,15 @@
         <action name="api/getCollection" class="com.akto.action.ApiCollectionsAction" method="fetchCollection">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="httpheader">
@@ -1036,9 +1539,18 @@
         <action name="api/addApisToCustomCollection" class="com.akto.action.ApiCollectionsAction" method="addApisToCustomCollection">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
-            <result name="SUCCESS"  type="json">
-            </result>
-            <result name="ERROR" type="json">
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
+            <result name="SUCCESS"  type="json">
+            </result>
+            <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
                 <param name="ignoreHierarchy">false</param>
                 <param name="includeProperties">^actionErrors.*</param>
@@ -1048,6 +1560,15 @@
         <action name="api/removeApisFromCustomCollection" class="com.akto.action.ApiCollectionsAction" method="removeApisFromCustomCollection">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="json">
@@ -1060,6 +1581,15 @@
         <action name="api/computeCustomCollections" class="com.akto.action.ApiCollectionsAction" method="computeCustomCollections">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="json">
@@ -1072,10 +1602,19 @@
         <action name="api/getCustomerEndpoints" class="com.akto.action.ApiCollectionsAction" method="fetchCustomerEndpoints">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
                 <param name="root">hasUsageEndpoints</param>
             </result>
-             <result name="ERROR" type="json">
+            <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
                 <param name="ignoreHierarchy">false</param>
                 <param name="includeProperties">^actionErrors.*</param>
@@ -1085,6 +1624,15 @@
         <action name="api/updateEnvType" class="com.akto.action.ApiCollectionsAction" method="updateEnvType">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1096,6 +1644,15 @@
         <action name="api/redactCollection" class="com.akto.action.ApiCollectionsAction" method="redactCollection">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="json">
@@ -1109,6 +1666,15 @@
         <action name="api/uploadHar" class="com.akto.action.HarAction">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">ACTIVE_ENDPOINTS</param>
             </interceptor-ref>
@@ -1129,6 +1695,15 @@
         <action name="api/uploadTcp" class="com.akto.action.HarAction" method="uploadTcp">
             <interceptor-ref name="defaultStack"/>
             <interceptor-ref name="json"/>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="httpheader">
@@ -1143,6 +1718,15 @@
                 <param name="featureLabel">API_COLLECTIONS</param>
             </interceptor-ref>
             <result name="SUCCESS"  type="json">
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             </result>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1159,6 +1743,15 @@
         <action name="api/createCustomCollection" class="com.akto.action.ApiCollectionsAction" method="createCustomCollection">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="json">
@@ -1171,6 +1764,15 @@
         <action name="api/getEndpointsFromConditions" class="com.akto.action.ApiCollectionsAction" method="getEndpointsFromConditions">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="json">
@@ -1183,6 +1785,15 @@
         <action name="api/addOrUpdatePostmanCred" class="com.akto.action.PostmanAction" method="addOrUpdateApiKey">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="httpheader">
@@ -1193,6 +1804,15 @@
         <action name="api/createPostmanApi" class="com.akto.action.PostmanAction" method="createPostmanApi">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="json">
@@ -1205,6 +1825,15 @@
         <action name="api/savePostmanCollection" class="com.akto.action.PostmanAction" method="savePostmanCollection">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="json">
@@ -1217,6 +1846,15 @@
         <action name="api/fetchPostmanWorkspaces" class="com.akto.action.PostmanAction" method="fetchWorkspaces">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="httpheader">
@@ -1227,6 +1865,15 @@
         <action name="api/fetchCollections" class="com.akto.action.PostmanAction" method="fetchCollections">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="json">
@@ -1239,6 +1886,15 @@
         <action name="api/logout" class="com.akto.action.LogoutAction">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
             </result>
         </action>
@@ -1246,6 +1902,15 @@
         <action name="auth0-logout" class="com.akto.action.LogoutAction" method="auth0Logout">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
             </result>
         </action>
@@ -1253,6 +1918,15 @@
         <action name="api/getPostmanCredential" class="com.akto.action.PostmanAction" method="fetchPostmanCred">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="httpheader">
@@ -1263,6 +1937,15 @@
         <action name="api/importPostmanWorkspace" class="com.akto.action.PostmanAction" method="importDataFromPostman">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">ACTIVE_ENDPOINTS</param>
             </interceptor-ref>
@@ -1281,6 +1964,15 @@
         <action name="api/addSlackWebhook" class="com.akto.action.ApiTokenAction" method="addSlackWebhook">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">AKTO_ALERTS</param>
             </interceptor-ref>
@@ -1299,6 +1991,15 @@
         <action name="api/deleteSlackWebhook" class="com.akto.action.ApiTokenAction" method="deleteSlackWebhook">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="httpheader">
@@ -1336,6 +2037,15 @@
         <action name="api/deleteApiToken" class="com.akto.action.ApiTokenAction" method="deleteApiToken">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="httpheader">
@@ -1346,6 +2056,15 @@
         <action name="api/fetchApiTokens" class="com.akto.action.ApiTokenAction" method="fetchApiTokens">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="httpheader">
@@ -1357,6 +2076,15 @@
         <action name="api/fetchEndpointTrafficData" class="com.akto.action.TrafficAction" method="fetchEndpointTrafficData">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TRAFFIC_FILTERS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="collectionInterceptor"/>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="httpheader">
@@ -1372,6 +2100,15 @@
         <action name="api/fetchSampleData" class="com.akto.action.TrafficAction" method="fetchSampleData">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">SAMPLE_DATA</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="collectionInterceptor"/>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="httpheader">
@@ -1387,6 +2124,15 @@
         <action name="api/deleteCollection" class="com.akto.action.ApiCollectionsAction" method="deleteCollection">
            <interceptor-ref name="json"/>
            <interceptor-ref name="defaultStack" />
+           <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
            <result name="SUCCESS"  type="json">
            </result>
            <result name="ERROR" type="httpheader">
@@ -1397,6 +2143,15 @@
         <action name="api/deleteMultipleCollections" class="com.akto.action.ApiCollectionsAction" method="deleteMultipleCollections">
            <interceptor-ref name="json"/>
            <interceptor-ref name="defaultStack" />
+           <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
            <result name="SUCCESS"  type="json">
            </result>
            <result name="ERROR" type="httpheader">
@@ -1407,16 +2162,34 @@
         <action name="api/fetchApiInfoList" class="com.akto.action.ApiInfoAction" method="fetchApiInfoList">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
-            <result name="SUCCESS"  type="json">
-            </result>
-            <result name="ERROR" type="httpheader">
-                <param name="status">401</param>
-            </result>
-        </action>
+             <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
+            <result name="SUCCESS"  type="json">
+            </result>
+            <result name="ERROR" type="httpheader">
+                <param name="status">401</param>
+            </result>
+        </action>
 
         <action name="api/getSingleEndpoint" class="com.akto.action.ApiInfoAction" method="fetchApiInfo">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
                 <param name="root">apiInfo</param>
             </result>
@@ -1430,6 +2203,15 @@
         <action name="api/fetchFilters" class="com.akto.action.FilterAction">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TRAFFIC_FILTERS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="httpheader">
@@ -1440,18 +2222,15 @@
         <action name="api/convertSampleDataToCurl" class="com.akto.action.ExportSampleDataAction" method="generateCurl">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
-            <result name="SUCCESS"  type="json">
-            </result>
-            <result name="ERROR" type="json">
-                <param name="statusCode">422</param>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">SAMPLE_DATA</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
                 <param name="ignoreHierarchy">false</param>
                 <param name="includeProperties">^actionErrors.*</param>
             </result>
-        </action>
-
-        <action name="tools/convertSampleDataToCurl" class="com.akto.action.ExportSampleDataAction" method="generateCurl">
-            <interceptor-ref name="json"/>
-            <interceptor-ref name="defaultStack" />
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="json">
@@ -1461,21 +2240,18 @@
             </result>
         </action>
 
-        <action name="api/convertSampleDataToCurl" class="com.akto.action.ExportSampleDataAction" method="generateCurl">
+        <action name="api/fetchSensitiveSampleData" class="com.akto.action.TrafficAction" method="fetchSensitiveSampleData">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
-            <result name="SUCCESS"  type="json">
-            </result>
-            <result name="ERROR" type="json">
-                <param name="statusCode">422</param>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">SAMPLE_DATA</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
                 <param name="ignoreHierarchy">false</param>
                 <param name="includeProperties">^actionErrors.*</param>
             </result>
-        </action>
-
-        <action name="api/fetchSensitiveSampleData" class="com.akto.action.TrafficAction" method="fetchSensitiveSampleData">
-            <interceptor-ref name="json"/>
-            <interceptor-ref name="defaultStack" />
             <interceptor-ref name="collectionInterceptor"/>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="httpheader">
@@ -1491,6 +2267,15 @@
         <action name="api/fetchDataTypes" class="com.akto.action.CustomDataTypeAction" method="fetchDataTypesForSettings">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">SENSITIVE_DATA</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="httpheader">
                 <param name="status">401</param>
@@ -1500,6 +2285,15 @@
         <action name="api/fetchTagConfigs" class="com.akto.action.TagConfigsAction" method="fetchTagConfigs">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TAGS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="httpheader">
                 <param name="status">401</param>
@@ -1509,6 +2303,15 @@
         <action name="api/fetchChanges" class="com.akto.action.observe.InventoryAction" method="fetchChanges">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="httpheader">
                 <param name="status">401</param>
@@ -1518,6 +2321,15 @@
         <action name="api/saveCustomDataType" class="com.akto.action.CustomDataTypeAction">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">SENSITIVE_DATA</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">CUSTOM_DATA_TYPES</param>
             </interceptor-ref>
@@ -1537,6 +2349,15 @@
         <action name="api/resetDataType" class="com.akto.action.CustomDataTypeAction" method="resetDataType" >
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">SENSITIVE_DATA</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1548,6 +2369,15 @@
         <action name="api/saveAktoDataType" class="com.akto.action.CustomDataTypeAction" method="saveAktoDataType">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">SENSITIVE_DATA</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1559,6 +2389,15 @@
         <action name="api/reviewCustomDataType" class="com.akto.action.CustomDataTypeAction" method="reviewCustomDataType">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">SENSITIVE_DATA</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1570,6 +2409,15 @@
         <action name="api/toggleDataTypeActiveParam" class="com.akto.action.CustomDataTypeAction" method="toggleDataTypeActiveParam">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">SENSITIVE_DATA</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1581,6 +2429,15 @@
         <action name="api/fetchDataTypeNames" class="com.akto.action.CustomDataTypeAction" method="fetchDataTypeNames">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">SENSITIVE_DATA</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="httpheader">
                 <param name="status">401</param>
@@ -1590,6 +2447,15 @@
         <action name="api/fetchCustomAuthTypes" class="com.akto.action.CustomAuthTypeAction" method="fetchCustomAuthTypes">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">AUTH_TYPE</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1601,6 +2467,15 @@
         <action name="api/addCustomAuthType" class="com.akto.action.CustomAuthTypeAction" method="addCustomAuthType">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">AUTH_TYPE</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1612,6 +2487,15 @@
         <action name="api/updateCustomAuthType" class="com.akto.action.CustomAuthTypeAction" method="updateCustomAuthType">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">AUTH_TYPE</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1624,6 +2508,15 @@
         <action name="api/resetAllCustomAuthTypes" class="com.akto.action.CustomAuthTypeAction" method="resetAllCustomAuthTypes">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">AUTH_TYPE</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1635,6 +2528,15 @@
         <action name="api/updateCustomAuthTypeStatus" class="com.akto.action.CustomAuthTypeAction" method="updateCustomAuthTypeStatus">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">AUTH_TYPE</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1650,7 +2552,8 @@
                 <param name="featureLabel">API_DATA_REDACTION</param>
             </interceptor-ref>
             <interceptor-ref name="roleAccessInterceptor">
-                <param name="rolesList">ADMIN</param>
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
             </interceptor-ref>
 
             <result name="FORBIDDEN" type="json">
@@ -1672,6 +2575,16 @@
         <action name="api/updateMergeAsyncOutside" class="com.akto.action.AdminSettingsAction" method="updateMergeAsyncOutside">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="httpheader">
                 <param name="status">401</param>
@@ -1681,6 +2594,16 @@
         <action name="api/updateGlobalRateLimit" class="com.akto.action.AdminSettingsAction" method="updateGlobalRateLimit">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="httpheader">
                 <param name="status">401</param>
@@ -1690,12 +2613,32 @@
         <action name="api/fetchAdminSettings" class="com.akto.action.AdminSettingsAction">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
         </action>
 
         <action name="api/updatePrivateCidrIps" class="com.akto.action.AdminSettingsAction" method="editPrivateCidrList">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
                 <param name="root">privateCidrList</param>
             </result>
@@ -1709,6 +2652,16 @@
         <action name="api/updatePartnerIps" class="com.akto.action.AdminSettingsAction" method="editPartnerIpList">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
                 <param name="root">partnerIpList</param>
             </result>
@@ -1722,6 +2675,16 @@
           <action name="api/saveTagConfig" class="com.akto.action.TagConfigsAction" method="saveTagConfig">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TAGS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1733,6 +2696,16 @@
         <action name="api/reviewTagConfig" class="com.akto.action.TagConfigsAction" method="reviewTagConfig">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TAGS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1744,6 +2717,16 @@
         <action name="api/toggleActiveTagConfig" class="com.akto.action.TagConfigsAction" method="toggleActiveTagConfig">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TAGS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1755,6 +2738,16 @@
         <action name="api/takeUpdate" class="com.akto.action.AccountAction" method="takeUpdate">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
 
             <result name="ERROR" type="httpheader">
@@ -1768,7 +2761,17 @@
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">TEST_RUNS</param>
             </interceptor-ref>
-            <result name="SUCCESS" type="json"/>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">START_TEST_RUN</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
+            <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
                 <param name="ignoreHierarchy">false</param>
@@ -1784,6 +2787,16 @@
         <action name="api/retrieveAllCollectionTests" class="com.akto.action.testing.StartTestAction" method="retrieveAllCollectionTests">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1795,6 +2808,16 @@
         <action name="api/getAllTestsCountMap" class="com.akto.action.testing.StartTestAction" method="computeAllTestsCountMap">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
                 <param name="root">allTestsCountMap</param>
             </result>
@@ -1808,6 +2831,16 @@
         <action name="api/getIssueSummaryInfo" class="com.akto.action.testing.StartTestAction" method="getIssueSummaryInfo">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
                 <param name="root">issuesSummaryInfoMap</param>
             </result>
@@ -1821,6 +2854,16 @@
         <action name="api/fetchTestingRunResultSummaries" class="com.akto.action.testing.StartTestAction" method="fetchTestingRunResultSummaries">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1832,6 +2875,16 @@
         <action name="api/fetchTestingRunResultSummary" class="com.akto.action.testing.StartTestAction" method="fetchTestingRunResultSummary">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1843,6 +2896,16 @@
         <action name="api/toggleTestingRunForCollection" class="com.akto.action.testing.StartTestAction" method="toggleTestingRunForCollection">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">START_TEST_RUN</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1854,6 +2917,16 @@
         <action name="api/addAuthMechanism" class="com.akto.action.testing.AuthMechanismAction" method="addAuthMechanism">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_CONFIG</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">AUTOMATED_AUTH_TOKEN</param>
             </interceptor-ref>
@@ -1873,6 +2946,16 @@
         <action name="api/triggerLoginSteps" class="com.akto.action.testing.AuthMechanismAction" method="triggerLoginFlowSteps">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_CONFIG</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1884,6 +2967,16 @@
         <action name="api/fetchAuthMechanismData" class="com.akto.action.testing.AuthMechanismAction" method="fetchAuthMechanismData">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_CONFIG</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1895,6 +2988,16 @@
         <action name="api/fetchAuthMechanismDataDoc" class="com.akto.action.testing.AuthMechanismAction" method="fetchAuthMechanismDataDoc">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_CONFIG</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1937,6 +3040,16 @@
         <action name="api/fetchAllSampleData" class="com.akto.action.TrafficAction" method="fetchAllSampleData">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">SAMPLE_DATA</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="collectionInterceptor"/>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="httpheader">
@@ -1952,6 +3065,16 @@
         <action name="api/fetchTestingRunResults" class="com.akto.action.testing.StartTestAction" method="fetchTestingRunResults">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1963,6 +3086,16 @@
         <action name="api/fetchVulnerableTestRunResults" class="com.akto.action.testing.StartTestAction" method="fetchVulnerableTestRunResults">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1974,6 +3107,16 @@
         <action name="api/fetchTestingRunResultFromTestingRun" class="com.akto.action.test_editor.SaveTestEditorAction" method="fetchTestingRunResultFromTestingRun">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1985,6 +3128,16 @@
         <action name="api/updateSetupType" class="com.akto.action.AdminSettingsAction" method="updateSetupType">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -1996,6 +3149,16 @@
         <action name="api/toggleNewMergingEnabled" class="com.akto.action.AdminSettingsAction" method="toggleNewMergingEnabled">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2008,7 +3171,8 @@
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
             <interceptor-ref name="roleAccessInterceptor">
-                <param name="rolesList">ADMIN</param>
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
             </interceptor-ref>
 
             <result name="FORBIDDEN" type="json">
@@ -2027,6 +3191,16 @@
         <action name="api/updateUrlSettings" class="com.akto.action.AdminSettingsAction" method="updateUrlSettings">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">DEFAULT_PAYLOADS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
                 <param name="root">allowRedundantEndpoints</param>
             </result>
@@ -2050,6 +3224,16 @@
         <action name="api/fetchLogs" class="com.akto.action.LogsAction" method="fetchLogs">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">LOGS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
 
             <result name="ERROR" type="httpheader">
@@ -2060,6 +3244,16 @@
         <action name="api/fetchLogsFromDb" class="com.akto.action.DbLogsAction" method="fetchLogsFromDb">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">LOGS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2071,6 +3265,16 @@
         <action name="api/fetchAllIssues" class="com.akto.action.testing_issues.IssuesAction" method="fetchAllIssues">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ISSUES</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="httpheader">
                 <param name="status">401</param>
@@ -2080,6 +3284,16 @@
         <action name="api/fetchVulnerableTestingRunResultsFromIssues" class="com.akto.action.testing_issues.IssuesAction" method="fetchVulnerableTestingRunResultsFromIssues">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ISSUES</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="httpheader">
                 <param name="status">401</param>
@@ -2089,6 +3303,16 @@
         <action name="api/fetchAffectedEndpoints" class="com.akto.action.testing_issues.IssuesAction" method="fetchAffectedEndpoints">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ISSUES</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="httpheader">
                 <param name="status">401</param>
@@ -2098,6 +3322,16 @@
         <action name="api/fetchAllSubCategories" class="com.akto.action.testing_issues.IssuesAction" method="fetchAllSubCategories">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ISSUES</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
                 <param name="enumAsBean">true</param>
             </result>
@@ -2109,6 +3343,16 @@
         <action name="api/fetchTestRoles" class="com.akto.action.testing.TestRolesAction" method="fetchAllRolesAndLogicalGroups">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_ROLES</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2120,6 +3364,16 @@
         <action name="api/addTestRoles" class="com.akto.action.testing.TestRolesAction" method="createTestRole">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_ROLES</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2131,6 +3385,16 @@
         <action name="api/deleteTestRole" class="com.akto.action.testing.TestRolesAction" method="deleteTestRole">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_ROLES</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2142,6 +3406,16 @@
         <action name="api/updateTestRoles" class="com.akto.action.testing.TestRolesAction" method="updateTestRoles">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_ROLES</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2153,8 +3427,18 @@
         <action name="api/deleteAuthFromRole" class="com.akto.action.testing.TestRolesAction" method="deleteAuthFromRole">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
-            <result name="SUCCESS" type="json"/>
-            <result name="ERROR" type="json">
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_ROLES</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
+            <result name="SUCCESS" type="json"/>
+            <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
                 <param name="ignoreHierarchy">false</param>
                 <param name="includeProperties">^actionErrors.*</param>
@@ -2164,6 +3448,16 @@
         <action name="api/addAuthToRole" class="com.akto.action.testing.TestRolesAction" method="addAuthToRole">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_ROLES</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2175,6 +3469,16 @@
         <action name="api/fetchTestingRunResult" class="com.akto.action.testing_issues.IssuesAction" method="fetchTestingRunResult">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="httpheader">
                 <param name="status">401</param>
@@ -2184,6 +3488,16 @@
         <action name="api/updateIssueStatus" class="com.akto.action.testing_issues.IssuesAction" method="updateIssueStatus">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ISSUES</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="status">401</param>
@@ -2193,6 +3507,16 @@
         <action name="api/bulkUpdateIssueStatus" class="com.akto.action.testing_issues.IssuesAction" method="bulkUpdateIssueStatus">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ISSUES</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="status">401</param>
@@ -2202,6 +3526,16 @@
         <action name="api/createWorkflowTest" class="com.akto.action.testing.WorkflowTestAction" method="createWorkflowTest">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">START_TEST_RUN</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
 
             <result name="ERROR" type="httpheader">
@@ -2212,6 +3546,16 @@
         <action name="api/editWorkflowTest" class="com.akto.action.testing.WorkflowTestAction" method="editWorkflowTest">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">START_TEST_RUN</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
 
             <result name="ERROR" type="httpheader">
@@ -2222,6 +3566,16 @@
         <action name="api/setWorkflowTestState" class="com.akto.action.testing.WorkflowTestAction" method="setWorkflowTestState">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
 
             <result name="ERROR" type="httpheader">
@@ -2232,6 +3586,16 @@
         <action name="api/exportWorkflowTestAsString" class="com.akto.action.testing.WorkflowTestAction" method="exportWorkflowTestAsString">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
 
             <result name="ERROR" type="httpheader">
@@ -2242,6 +3606,16 @@
         <action name="api/editWorkflowNodeDetails" class="com.akto.action.testing.WorkflowTestAction" method="editWorkflowNodeDetails">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
 
             <result name="ERROR" type="httpheader">
@@ -2252,6 +3626,16 @@
         <action name="api/fetchWorkflowTests" class="com.akto.action.testing.WorkflowTestAction" method="fetchWorkflowTests">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
 
             <result name="ERROR" type="httpheader">
@@ -2262,6 +3646,16 @@
         <action name="api/fetchWorkflowResult" class="com.akto.action.testing.AuthMechanismAction" method="fetchWorkflowResult">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2273,17 +3667,16 @@
         <action name="otp" class="com.akto.action.misc.OtpAction" method="fetchRecentOtp">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
-            <result name="SUCCESS" type="json"/>
-            <result name="ERROR" type="json">
-                <param name="statusCode">422</param>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
                 <param name="ignoreHierarchy">false</param>
                 <param name="includeProperties">^actionErrors.*</param>
             </result>
-        </action>
-
-        <action name="send_otp" class="com.akto.action.misc.OtpAction">
-            <interceptor-ref name="json"/>
-            <interceptor-ref name="defaultStack" />
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2292,20 +3685,19 @@
             </result>
         </action>
 
-        <action name="api/convertSamleDataToBurpRequest" class="com.akto.action.ExportSampleDataAction" method="generateBurpRequest">
+        <action name="send_otp" class="com.akto.action.misc.OtpAction">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
-            <result name="SUCCESS" type="json"/>
-            <result name="ERROR" type="json">
-                <param name="statusCode">422</param>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
                 <param name="ignoreHierarchy">false</param>
                 <param name="includeProperties">^actionErrors.*</param>
             </result>
-        </action>
-
-        <action name="tools/convertSamleDataToBurpRequest" class="com.akto.action.ExportSampleDataAction" method="generateBurpRequest">
-            <interceptor-ref name="json"/>
-            <interceptor-ref name="defaultStack" />
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2317,6 +3709,16 @@
         <action name="api/convertSamleDataToBurpRequest" class="com.akto.action.ExportSampleDataAction" method="generateBurpRequest">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">SAMPLE_DATA</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2328,6 +3730,16 @@
         <action name="fetchLatestMessageId" class="com.akto.action.misc.OtpAction" method="fetchLatestMessageId">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2339,6 +3751,16 @@
         <action name="fetchOtpFromMySms" class="com.akto.action.misc.OtpAction" method="fetchOtpFromMySms">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2350,6 +3772,16 @@
         <action name="api/importInBurp" class="com.akto.action.ExportSampleDataAction" method="importInBurp">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2363,7 +3795,17 @@
             <interceptor-ref name="defaultStack" />
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">AKTO_ALERTS</param>
-            </interceptor-ref>            
+            </interceptor-ref>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>            
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2380,6 +3822,16 @@
         <action name="api/deleteScheduledWorkflowTests" class="com.akto.action.testing.StartTestAction" method="deleteScheduledWorkflowTests">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2391,6 +3843,16 @@
         <action name="api/fetchWorkflowTestingRun" class="com.akto.action.testing.StartTestAction" method="fetchWorkflowTestingRun">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2404,6 +3866,16 @@
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">AKTO_ALERTS</param>
             </interceptor-ref>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2420,6 +3892,16 @@
         <action name="api/fetchWorkflowTestingSchedule" class="com.akto.action.testing.StartTestAction" method="fetchWorkflowTestingSchedule">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2431,6 +3913,16 @@
         <action name="api/deleteTestRuns" class="com.akto.action.testing.StartTestAction" method="deleteTestRunsAction">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2442,6 +3934,16 @@
         <action name="api/deleteTestRunsFromSummaries" class="com.akto.action.testing.StartTestAction" method="deleteTestDataFromSummaryId">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2453,6 +3955,16 @@
         <action name="api/fetchCustomWebhooks" class="com.akto.action.WebhookAction" method="fetchCustomWebhooks">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2464,6 +3976,16 @@
         <action name="api/downloadWorkflowAsJson" class="com.akto.action.testing.WorkflowTestAction" method="downloadWorkflowAsJson">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2475,6 +3997,16 @@
         <action name="api/changeStatus" class="com.akto.action.WebhookAction" method="changeStatus">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2489,6 +4021,16 @@
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">AKTO_ALERTS</param>
             </interceptor-ref>
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2516,6 +4058,16 @@
         <action name="api/stopAllTests" class="com.akto.action.testing.StartTestAction" method="stopAllTests">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">START_TEST_RUN</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2527,6 +4079,16 @@
         <action name="api/stopTest" class="com.akto.action.testing.StartTestAction" method="stopTest">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">START_TEST_RUN</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2538,6 +4100,16 @@
         <action name="api/fetchMetadataFilters" class="com.akto.action.testing.StartTestAction" method="fetchMetadataFilters">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2549,6 +4121,16 @@
         <action name="api/fetchLatestWebhookResult" class="com.akto.action.WebhookAction" method="fetchLatestWebhookResult">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2560,6 +4142,16 @@
         <action name="api/fetchTestRunResultDetails" class="com.akto.action.testing.StartTestAction" method="fetchTestRunResultDetails">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
                 <param name="enumAsBean">true</param>
             </result>
@@ -2568,11 +4160,21 @@
                 <param name="ignoreHierarchy">false</param>
                 <param name="includeProperties">^actionErrors.*</param>
             </result>
-        </action>
-
-        <action name="api/fetchIssueFromTestRunResultDetails" class="com.akto.action.testing.StartTestAction" method="fetchIssueFromTestRunResultDetails">
-            <interceptor-ref name="json"/>
-            <interceptor-ref name="defaultStack" />
+        </action>
+
+        <action name="api/fetchIssueFromTestRunResultDetails" class="com.akto.action.testing.StartTestAction" method="fetchIssueFromTestRunResultDetails">
+            <interceptor-ref name="json"/>
+            <interceptor-ref name="defaultStack" />
+             <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ISSUES</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
             </result>
             <result name="ERROR" type="json">
@@ -2585,6 +4187,16 @@
         <action name="api/fetchUsageTestRuns" class="com.akto.action.testing.StartTestAction" method="getUsageTestRuns">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">BILLING</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
                 <param name="root">testRunsByUser</param>
             </result>
@@ -2598,6 +4210,16 @@
         <action name="api/fetchActiveTestRunsStatus" class="com.akto.action.testing.StartTestAction" method="getCurrentTestStateStatus">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_RESULTS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
                 <param name="root">currentTestsStatus</param>
             </result>
@@ -2612,6 +4234,16 @@
          <action name="api/fetchQuickStartPageState" class="com.akto.action.quick_start.QuickStartAction" method="fetchQuickStartPageState">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
                  <param name="excludeProperties">
                     stackState,availableLBs,dashboardHasNecessaryRole,isFirstSetup,selectedLBs
@@ -2626,6 +4258,16 @@
         <action name="api/fetchLoadBalancers" class="com.akto.action.quick_start.QuickStartAction" method="fetchLoadBalancers">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2636,6 +4278,16 @@
         <action name="api/saveLoadBalancers" class="com.akto.action.quick_start.QuickStartAction" method="saveLoadBalancers">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">ADVANCED_TRAFFIC_CONNECTORS</param>
             </interceptor-ref>
@@ -2657,6 +4309,16 @@
         <action name="api/fetchRuntimeHelmCommand" class="com.akto.action.quick_start.QuickStartAction" method="fetchRuntimeHelmCommand">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
                 <param name="stackState">stackState</param>
             </result>
@@ -2670,6 +4332,16 @@
         <action name="api/checkStackCreationProgress" class="com.akto.action.quick_start.QuickStartAction" method="checkStackCreationProgress">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name= "ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2681,6 +4353,16 @@
         <action name="api/createRuntimeStack" class="com.akto.action.quick_start.QuickStartAction" method="createRuntimeStack">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">ADVANCED_TRAFFIC_CONNECTORS</param>
             </interceptor-ref>
@@ -2700,6 +4382,16 @@
         <action name="api/fetchEndpointsBasedOnHostName" class="com.akto.action.observe.InventoryAction" method="fetchEndpointsBasedOnHostName">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
                 <param name="root">endpoints</param>
             </result>
@@ -2713,6 +4405,16 @@
         <action name="saveOtpData/{uuid}" class="com.akto.action.testing.OtpTestDataAction" method="saveOtpData">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2724,6 +4426,16 @@
         <action name="api/fetchOtpData/{uuid}" class="com.akto.action.testing.OtpTestDataAction" method="fetchOtpData">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
                 <param name="includeProperties">^otp.*</param>
             </result>
@@ -2737,6 +4449,16 @@
         <action name="api/triggerSingleLoginFlow" class="com.akto.action.testing.AuthMechanismAction" method="triggerSingleLoginFlowStep">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_CONFIG</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2748,6 +4470,16 @@
         <action name="api/downloadBurpPluginJar" class="com.akto.action.BurpJarAction" >
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2759,6 +4491,16 @@
         <action name="api/fetchBurpPluginDownloadLink" class="com.akto.action.BurpJarAction" method="fetchBurpPluginDownloadLink" >
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2770,6 +4512,16 @@
         <action name="api/fetchBurpCredentials" class="com.akto.action.BurpJarAction" method="fetchBurpCredentials" >
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2781,6 +4533,16 @@
         <action name="api/sendHealthCheck" class="com.akto.action.BurpJarAction" method="sendHealthCheck">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2792,6 +4554,16 @@
         <action name="api/fetchRecordedFlowOutput" class="com.akto.action.testing.LoginRecorderAction" method="fetchRecordedFlowOutput">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_CONFIG</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json" />
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2803,6 +4575,16 @@
         <action name="api/uploadRecordedFlow" class="com.akto.action.testing.LoginRecorderAction" method="uploadRecordedFlow">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_CONFIG</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
             </result>
             <result name="ERROR" type="json">
@@ -2815,6 +4597,16 @@
         <action name="api/fetchBurpPluginInfo" class="com.akto.action.BurpJarAction" method="fetchBurpPluginInfo">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json" />
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2826,6 +4618,16 @@
         <action name="api/fetchUserLastLoginTs" class="com.akto.action.user.UserInfoAction" method="fetchUserLastLoginTs">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="json">
@@ -2838,6 +4640,16 @@
         <action name="api/updateAktoUIMode" class="com.akto.action.user.UserInfoAction" method="updateAktoUIMode">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="json">
@@ -2850,6 +4662,16 @@
         <action name="api/fetchSubTypeCountMap" class="com.akto.action.observe.InventoryAction" method="fetchSubTypeCountMap">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ISSUES</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="json">
@@ -2862,6 +4684,16 @@
         <action name="api/fetchTestingLogs" class="com.akto.action.testing.WorkflowTestAction" method="fetchTestingLogs">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">LOGS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
                 <param name="includeProperties">^testingLogs.*</param>
             </result>
@@ -2875,6 +4707,16 @@
         <action name="api/runTestOnboarding" class="com.akto.action.OnboardingAction" method="runTestOnboarding">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2886,6 +4728,16 @@
         <action name="api/fetchTestSuites" class="com.akto.action.OnboardingAction" method="fetchTestSuites">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_EDITOR</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
                 <param name="enumAsBean">true</param>
             </result>
@@ -2894,11 +4746,21 @@
                 <param name="ignoreHierarchy">false</param>
                 <param name="includeProperties">^actionErrors.*</param>
             </result>
-        </action>
-
-        <action name="api/skipOnboarding" class="com.akto.action.OnboardingAction" method="skipOnboarding">
-            <interceptor-ref name="json"/>
-            <interceptor-ref name="defaultStack" />
+        </action>
+
+        <action name="api/skipOnboarding" class="com.akto.action.OnboardingAction" method="skipOnboarding">
+            <interceptor-ref name="json"/>
+            <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
                 <param name="enumAsBean">true</param>
             </result>
@@ -2912,6 +4774,16 @@
         <action name="api/ask_ai" class="com.akto.action.gpt.GptAction" method="askAi">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ASK_GPT</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">AKTO_GPT_AI</param>
             </interceptor-ref>
@@ -2931,6 +4803,16 @@
         <action name="api/fetchAktoGptConfig" class="com.akto.action.gpt.GptConfigAction" method="fetchAktoGptConfig">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ASK_GPT</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2942,6 +4824,16 @@
         <action name="api/saveAktoGptConfig" class="com.akto.action.gpt.GptConfigAction" method="saveAktoGptConfig">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ASK_GPT</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2953,6 +4845,16 @@
         <action name="api/fetchTrafficMetrics" class="com.akto.action.traffic_metrics.TrafficMetricsAction">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -2964,6 +4866,16 @@
         <action name="api/fetchTrafficMetricsDesciptions" class="com.akto.action.traffic_metrics.TrafficMetricsAction" method="fetchTrafficMetricsDesciptions">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ASK_GPT</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
                 <param name="enumAsBean">true</param>
             </result>
@@ -2977,6 +4889,16 @@
         <action name="api/importDataFromPostmanFile" class="com.akto.action.PostmanAction" method="importDataFromPostmanFile">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">ACTIVE_ENDPOINTS</param>
             </interceptor-ref>
@@ -2996,6 +4918,16 @@
         <action name="api/ingestPostman" class="com.akto.action.PostmanAction" method="importFile">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">ACTIVE_ENDPOINTS</param>
             </interceptor-ref>
@@ -3015,6 +4947,16 @@
         <action name="api/fetchPostmanImportLogs" class="com.akto.action.PostmanAction" method="fetchImportLogs">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">ACTIVE_ENDPOINTS</param>
             </interceptor-ref>
@@ -3034,6 +4976,16 @@
         <action name="api/deletePostmanImportLogs" class="com.akto.action.PostmanAction" method="markImportForDeletion">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">ACTIVE_ENDPOINTS</param>
             </interceptor-ref>
@@ -3053,6 +5005,16 @@
         <action name="api/fetchActiveLoaders" class="com.akto.action.LoadersAction" method="fetchActiveLoaders">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json">
                 <param name="enumAsBean">true</param>
             </result>
@@ -3066,6 +5028,16 @@
         <action name="api/closeLoader" class="com.akto.action.LoadersAction" method="closeLoader">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3077,6 +5049,16 @@
         <action name="api/setTestInactive" class="com.akto.action.test_editor.SaveTestEditorAction" method="setTestInactive">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_EDITOR</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3088,6 +5070,16 @@
         <action name="api/addTestLibrary" class="com.akto.action.test_editor.SaveTestEditorAction" method="addTestLibrary">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">EXTERNAL_TEST_LIBRARY</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3099,6 +5091,16 @@
         <action name="api/removeTestLibrary" class="com.akto.action.test_editor.SaveTestEditorAction" method="removeTestLibrary">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">EXTERNAL_TEST_LIBRARY</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3110,6 +5112,16 @@
         <action name="api/syncCustomLibrary" class="com.akto.action.test_editor.SaveTestEditorAction" method="syncCustomLibrary">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">EXTERNAL_TEST_LIBRARY</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3121,6 +5133,16 @@
         <action name="api/fetchCustomTestsCount" class="com.akto.action.test_editor.SaveTestEditorAction" method="fetchCustomTestsCount">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">EXTERNAL_TEST_LIBRARY</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
              <result name="SUCCESS" type="json">
                 <param name="enumAsBean">true</param>
             </result>
@@ -3134,6 +5156,16 @@
         <action name="api/saveTestEditorFile" class="com.akto.action.test_editor.SaveTestEditorAction" method="saveTestEditorFile">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_EDITOR</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3146,6 +5178,16 @@
         <action name="api/toggleDebugLogsFeature" class="com.akto.action.AdminSettingsAction" method="toggleDebugLogsFeature">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3157,6 +5199,16 @@
         <action name="api/addFilterHeaderValueMap" class="com.akto.action.AdminSettingsAction" method="addFilterHeaderValueMap">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3168,6 +5220,16 @@
         <action name="api/addApiCollectionNameMapper" class="com.akto.action.AdminSettingsAction" method="addApiCollectionNameMapper">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3178,6 +5240,16 @@
         <action name="api/deleteApiCollectionNameMapper" class="com.akto.action.AdminSettingsAction" method="deleteApiCollectionNameMapper">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3189,6 +5261,16 @@
         <action name="api/runTestForGivenTemplate" class="com.akto.action.test_editor.SaveTestEditorAction" method="runTestForGivenTemplate">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">TEST_EDITOR</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3225,6 +5307,16 @@
         <action name="callback" class="com.akto.action.SignupAction" method="registerViaAuth0">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_ACTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="root">code</param>
@@ -3234,6 +5326,16 @@
         <action name="addUserToAccount" class="com.akto.action.AddUserToAccountAction" method="execute">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_ACTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"   type="json"/>
             <result name="ERROR" type="json">
                 <param name="root">code</param>
@@ -3244,6 +5346,16 @@
         <action name="api/updateTrafficAlertThresholdSeconds" class="com.akto.action.AdminSettingsAction" method="updateTrafficAlertThresholdSeconds">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3255,6 +5367,16 @@
         <action name="api/deMergeApi" class="com.akto.action.observe.InventoryAction" method="deMergeApi">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="json">
@@ -3278,6 +5400,16 @@
         <action name="api/testIntegration" class="com.akto.action.JiraIntegrationAction" method="testIntegration" >
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">JIRA_INTEGRATION</param>
             </interceptor-ref>
@@ -3297,6 +5429,16 @@
         <action name="api/addIntegration" class="com.akto.action.JiraIntegrationAction" method="addIntegration" >
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">JIRA_INTEGRATION</param>
             </interceptor-ref>
@@ -3316,6 +5458,16 @@
         <action name="api/fetchIntegration" class="com.akto.action.JiraIntegrationAction" method="fetchIntegration" >
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3327,6 +5479,16 @@
         <action name="api/createJiraIssue" class="com.akto.action.JiraIntegrationAction" method="createIssue" >
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ISSUES</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3338,6 +5500,16 @@
         <action name="api/attachFileToIssue" class="com.akto.action.JiraIntegrationAction" method="attachFileToIssue" >
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ISSUES</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS" type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3348,6 +5520,16 @@
         <action name="api/fetchApiDependencies" class="com.akto.action.DependencyAction">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="httpheader">
                 <param name="status">401</param>
@@ -3357,6 +5539,16 @@
         <action name="api/getRiskScoreRangeMap" class="com.akto.action.DashboardAction" method="fetchRiskScoreCountMap">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
                 <param name="root">riskScoreCountMap</param>
             </result>
@@ -3368,6 +5560,16 @@
         <action name="api/getIssuesTrend" class="com.akto.action.DashboardAction" method="fetchIssuesTrend">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">ISSUES</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
                 <param name="root">issuesTrendMap</param>
             </result>
@@ -3379,6 +5581,16 @@
         <action name="api/getRecentActivities" class="com.akto.action.DashboardAction" method="fetchRecentActivities">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_ACTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="httpheader">
@@ -3389,6 +5601,16 @@
         <action name="api/getIntegratedConnectionsInfo" class="com.akto.action.DashboardAction" method="fetchIntegratedConnections">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_ACTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
                 <param name="root">integratedConnectionsInfo</param>
             </result>
@@ -3400,6 +5622,16 @@
         <action name="api/markConnectionAsSkipped" class="com.akto.action.DashboardAction" method="markConnectionAsSkipped">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">INTEGRATIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
             </result>
             <result name="ERROR" type="httpheader">
@@ -3409,6 +5641,16 @@
         <action name="api/provisionSubscription" class="com.akto.action.billing.UsageAction" method="provisionSubscription">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">BILLING</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
                 <param name="root">checkoutResult</param>
             </result>
@@ -3422,6 +5664,16 @@
         <action name="api/calcUsage" class="com.akto.action.billing.UsageAction" method="calcUsage">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">BILLING</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
                 <param name="root">checkoutResult</param>
             </result>
@@ -3435,6 +5687,16 @@
         <action name="api/syncWithAkto" class="com.akto.action.billing.UsageAction" method="syncWithAkto">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">BILLING</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
                 <param name="root">checkoutResult</param>
             </result>
@@ -3448,6 +5710,16 @@
         <action name="api/getCustomerStiggDetails" class="com.akto.action.billing.UsageAction" method="getCustomerStiggDetails">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">BILLING</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3459,6 +5731,16 @@
         <action name="api/refreshUsageDataForOrg" class="com.akto.action.billing.UsageAction" method="refreshUsageData">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">BILLING</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json">
                 <param name="root">checkoutResult</param>
             </result>
@@ -3472,6 +5754,16 @@
         <action name="api/fetchDefaultPayload" class="com.akto.action.settings.DefaultPayloadAction" method="fetchDefaultPayload">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">BILLING</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3483,6 +5775,16 @@
         <action name="api/fetchAllDefaultPayloads" class="com.akto.action.settings.DefaultPayloadAction" method="fetchAllDefaultPayloads">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">DEFAULT_PAYLOADS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3494,6 +5796,16 @@
         <action name="api/saveDefaultPayload" class="com.akto.action.settings.DefaultPayloadAction" method="saveDefaultPayload">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">DEFAULT_PAYLOADS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3505,6 +5817,16 @@
         <action name="api/buildDependencyTable" class="com.akto.action.DependencyAction" method="buildDependencyTable">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3517,6 +5839,16 @@
         <action name="api/invokeDependencyTable" class="com.akto.action.DependencyAction" method="invokeDependencyTable">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3528,6 +5860,16 @@
         <action name="api/saveReplaceDetails" class="com.akto.action.DependencyAction" method="saveReplaceDetails">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3539,6 +5881,16 @@
         <action name="api/saveGlobalVars" class="com.akto.action.DependencyAction" method="saveGlobalVars">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3550,6 +5902,16 @@
         <action name="api/fetchGlobalVars" class="com.akto.action.DependencyAction" method="fetchGlobalVars">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3561,6 +5923,16 @@
         <action name="api/fetchTestCollectionConfiguration" class="com.akto.action.testing.TestCollectionConfigurationAction" method="fetchTestCollectionConfiguration">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_CONFIG</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3572,6 +5944,16 @@
         <action name="api/fetchPropertyIds" class="com.akto.action.testing.TestCollectionConfigurationAction" method="fetchPropertyIds">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_CONFIG</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3583,6 +5965,16 @@
         <action name="api/fetchNonStandardHeaderKeys" class="com.akto.action.testing.TestCollectionConfigurationAction" method="fetchNonStandardHeaderKeys">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_CONFIG</param>
+                <param name="accessType">READ</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
             <result name="SUCCESS"  type="json"/>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
@@ -3594,7 +5986,17 @@
         <action name="api/syncExtractedAPIs" class="com.akto.action.CodeAnalysisAction" method="syncExtractedAPIs" >
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
-             <interceptor-ref name="usageInterceptor">
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
+            <interceptor-ref name="usageInterceptor">
                 <param name="featureLabel">CODE_ANALYSIS</param>
             </interceptor-ref>
             <result name="SUCCESS" type="json"/>
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/InviteUserModal.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/InviteUserModal.jsx
index 43ffcb062c..91729ce3c8 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/InviteUserModal.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/InviteUserModal.jsx
@@ -1,13 +1,29 @@
 import { Modal, Text, TextField } from "@shopify/polaris"
-import { useState, useRef } from "react"
+import { useState, useRef, useCallback } from "react"
 import func from "@/util/func"
 import Store from "../../../store"
 import settingRequests from "../api"
+import Dropdown from "../../../components/layouts/Dropdown"
 
 const InviteUserModal = ({ inviteUser, setInviteUser, toggleInviteUserModal }) => {
     const setToastConfig = Store(state => state.setToastConfig)
     const ref = useRef(null)
     const [inviteEmail, setInviteEmail] = useState()
+    const [inviteRole, setInviteRole] = useState('GUEST')
+
+    const rolesOptions = [
+        {label: 'Guest', value: 'GUEST'},
+        {label: 'Admin', value: 'ADMIN'},
+        {label: 'Security engineer', value: 'MEMBER'},
+        {label: 'Developer', value: 'DEVELOPER'},
+    ]
+
+    const handleRoleSelectChange = useCallback(
+        (value) => {
+            setInviteRole(value)
+        },
+        [],
+    );
 
     const handleSendInvitation = async () => {
         setInviteUser(previousState => ({
@@ -39,6 +55,7 @@ const InviteUserModal = ({ inviteUser, setInviteUser, toggleInviteUserModal }) =
         })
 
         setInviteEmail("")
+        setInviteRole("GUEST")
     }
 
     const handleCopyInvitation = () => {
@@ -76,6 +93,12 @@ const InviteUserModal = ({ inviteUser, setInviteUser, toggleInviteUserModal }) =
                         We'll use this address if we need to contact you about your account.
                     </Text>
 
+                    <Dropdown
+                        id={"inviteRoleSelection"}
+                        selected={handleRoleSelectChange}
+                        menuItems={rolesOptions} 
+                        initial={inviteRole} />
+
                 </Modal.Section>
             </Modal>
         )
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
index 782d21ee2c..7e27a8e0d2 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
@@ -1,12 +1,16 @@
-import { Avatar, Banner, Button, Card, LegacyCard, Modal, Page, ResourceItem, ResourceList, Scrollable, Text, TextContainer, TextField } from "@shopify/polaris"
-import { useCallback, useEffect, useState } from "react";
+import AktoButton from './../../../components/shared/AktoButton';
+import { ActionList, Avatar, Banner, LegacyCard, Link, Page, Popover, ResourceItem, ResourceList, Text } from "@shopify/polaris"
+import { DeleteMajor, TickMinor } from "@shopify/polaris-icons"
+import { useEffect, useState } from "react";
 import settingRequests from "../api";
 import func from "@/util/func";
 import InviteUserModal from "./InviteUserModal";
 import Store from "../../../store";
+import PersistStore from '../../../../main/PersistStore';
 
 const Users = () => {
     const username = Store(state => state.username)
+    const userRole = PersistStore(state => state.userRole)
 
     const [inviteUser, setInviteUser] = useState({
         isActive: false,
@@ -18,6 +22,86 @@ const Users = () => {
     const [loading, setLoading] = useState(false)
     const [users, setUsers] = useState([])
 
+    const [roleSelectionPopup, setRoleSelectionPopup] = useState({})
+
+    const rolesOptions = [
+        {
+            items: [
+            {
+                content: 'Admin',
+                role: 'ADMIN',
+                icon: <div style={{padding: "10px"}}/>
+            },
+            {
+                content: 'Security Engineer',
+                role: 'MEMBER',
+                icon: <div style={{padding: "10px"}}/>
+            },
+            {
+                content: 'Developer',
+                role: 'DEVELOPER',
+                icon: <div style={{padding: "10px"}}/>
+            },
+            {
+                content: 'Guest',
+                role: 'GUEST',
+                icon: <div style={{padding: "10px"}}/>
+            }]
+        },
+        {
+            items: [{
+                destructive: true,
+                content: 'Remove',
+                role: 'REMOVE',
+                icon: DeleteMajor
+            }]
+        }
+    ]
+
+    const handleRoleSelectChange = async (id, newRole, login) => {
+        if(newRole === 'REMOVE') {
+            // await handleRemoveUser(login)
+            console.log("removing user ", login)
+            toggleRoleSelectionPopup(id)
+            return
+        }
+
+        // Call Update Role API
+        setUsers(users.map(user => user.login === login ? { ...user, role: newRole } : user))
+        setRoleSelectionPopup(prevState => ({ ...prevState, [login]: false }))
+        console.log(newRole, login)
+
+        toggleRoleSelectionPopup(id)
+    }
+
+    const toggleRoleSelectionPopup = (id) => {
+        setRoleSelectionPopup(prevState => ({
+            ...prevState,
+            [id]: !prevState[id]
+        }));
+    }
+
+    const getRolesOptionsWithTick = (currentRole) => {
+        return rolesOptions.map(section => ({
+            ...section,
+            items: section.items.map(item => ({
+                ...item,
+                icon: item.role === currentRole ? TickMinor : item.icon
+            }))
+        }));
+    }
+
+    const getRoleDisplayName = (role) => {
+        for(let section of rolesOptions) {
+            for(let item of section.items) {
+                if(item.role === role) {
+                    return item.content;
+                }
+            }
+        }
+        return role;
+    }
+
     const getTeamData = async () => {
         setLoading(true);
         const usersResponse = await settingRequests.getTeamData()
@@ -32,11 +116,6 @@ const Users = () => {
     const isLocalDeploy = false;
     const currentUser = users.find(user => user.login === username)
 
-    let isAdmin = false
-    if (currentUser) {
-        isAdmin = currentUser.role === "ADMIN"
-    } 
-
     const toggleInviteUserModal = () => {
         setInviteUser({
             isActive: !inviteUser.isActive,
@@ -55,14 +134,14 @@ const Users = () => {
         await settingRequests.makeAdmin(login)
         func.setToast(true, false, "User " + login + " made admin successfully")
     }
-
+    
     return (
         <Page
             title="Users"
             primaryAction={{
                 content: 'Invite user',
                 onAction: () => toggleInviteUserModal(),
-                disabled: isLocalDeploy
+                'disabled': (isLocalDeploy || userRole === 'GUEST')
             }}
             divider
         >
@@ -80,30 +159,47 @@ const Users = () => {
                 </Banner>
             }
             <br />
-            <Text variant="headingMd">Team details</Text>
-            <Text variant="bodyMd">Find and manage your team permissions here</Text>
+            
+            <Banner>
+                <Text variant="headingMd">Role permissions</Text>
+                <Text variant="bodyMd">Each role have different permissions. <Link url="https://docs.akto.io/" target="_blank">Learn more</Link></Text>
+            </Banner>
+
             <div style={{ paddingTop: "20px" }}>
                 <LegacyCard>
                     <ResourceList
                         resourceName={{ singular: 'user', plural: 'users' }}
                         items={users}
                         renderItem={(item) => {
-                            const { id, login, role } = item;
-
+                            const { id, name, login, role } = item;
                             const initials = func.initials(login)
                             const media = <Avatar user size="medium" name={login} initials={initials} />
-                            const shortcutActions = username !== login && isAdmin  ? 
+                            const shortcutActions = username !== login && role !== currentUser.role && currentUser.role !== "GUEST" ? 
                                 [
                                     {
-                                        content: 'Remove user',
-                                        onAction: () => {handleRemoveUser(login)},
-                                    },
-                                    ( role.toUpperCase() === "MEMBER" ) &&
+                                        content: <Popover
+                                                    active={roleSelectionPopup[id]}
+                                                    onClose={() => toggleRoleSelectionPopup(id)}
+                                                    activator={<AktoButton disclosure onClick={() => toggleRoleSelectionPopup(id)}>{getRoleDisplayName(role)}</AktoButton>}
+                                                 >
+                                                    <ActionList
+                                                        actionRole="menuitem"
+                                                        sections={getRolesOptionsWithTick(role).map(section => ({
+                                                            ...section,
+                                                            items: section.items.map(item => ({
+                                                                ...item,
+                                                                onAction: () => handleRoleSelectChange(id, item.role, login)
+                                                            }))
+                                                        }))}
+                                                    />
+                                                 </Popover>
+                                    }
+                                ] : [
                                     {
-                                        content: 'Make admin',
-                                        onAction: () => {handleMakeAdmin(login)},
+                                        content: <Text color="subdued">{getRoleDisplayName(role)}</Text>,
+                                        url: '#',
                                     }
-                                ] : []
+                                ]
 
                             return (
                                 <ResourceItem
@@ -113,10 +209,10 @@ const Users = () => {
                                     persistActions
                                 >
                                     <Text variant="bodyMd" fontWeight="bold" as="h3">
-                                        {login}
+                                        {name}
                                     </Text>
                                     <Text variant="bodyMd">
-                                        {role}
+                                        {login}
                                     </Text>
                                 </ResourceItem>
                             );
@@ -138,4 +234,4 @@ const Users = () => {
     )
 }
 
-export default Users
+export default Users
\ No newline at end of file
diff --git a/libs/dao/src/main/java/com/akto/dto/rbac/DeveloperRoleStrategy.java b/libs/dao/src/main/java/com/akto/dto/rbac/DeveloperRoleStrategy.java
index 703ea95842..a63852145b 100644
--- a/libs/dao/src/main/java/com/akto/dto/rbac/DeveloperRoleStrategy.java
+++ b/libs/dao/src/main/java/com/akto/dto/rbac/DeveloperRoleStrategy.java
@@ -17,7 +17,10 @@ public Role[] getRoleHierarchy() {
     public Map<Feature, ReadWriteAccess> getFeatureAccessMap() {
         Map<Feature, ReadWriteAccess> accessMap = new HashMap<>();
         for (AccessGroups group : AccessGroups.getAccessGroups()) {
-            ReadWriteAccess access = group == AccessGroups.SETTINGS ? ReadWriteAccess.READ_WRITE : ReadWriteAccess.READ;
+            ReadWriteAccess access = ReadWriteAccess.READ ;
+            if(group == AccessGroups.SETTINGS ){
+                access = ReadWriteAccess.READ_WRITE;
+            }
             for (Feature feature : Feature.getFeaturesForAccessGroup(group)) {
                 accessMap.put(feature, access);
             }
diff --git a/libs/dao/src/main/java/com/akto/dto/rbac/MemberRoleStrategy.java b/libs/dao/src/main/java/com/akto/dto/rbac/MemberRoleStrategy.java
index 29ba4d7628..d970e197b1 100644
--- a/libs/dao/src/main/java/com/akto/dto/rbac/MemberRoleStrategy.java
+++ b/libs/dao/src/main/java/com/akto/dto/rbac/MemberRoleStrategy.java
@@ -17,7 +17,10 @@ public Role[] getRoleHierarchy() {
     public Map<Feature, ReadWriteAccess> getFeatureAccessMap() {
         Map<Feature, ReadWriteAccess> accessMap = new HashMap<>();
         for (AccessGroups group : AccessGroups.getAccessGroups()) {
-            ReadWriteAccess access = group == AccessGroups.SETTINGS ? ReadWriteAccess.READ : ReadWriteAccess.READ_WRITE;
+            ReadWriteAccess access = ReadWriteAccess.READ ;
+            if(group != AccessGroups.SETTINGS && group != AccessGroups.ADMIN){
+                access = ReadWriteAccess.READ_WRITE;
+            }
             for (Feature feature : Feature.getFeaturesForAccessGroup(group)) {
                 accessMap.put(feature, access);
             }
diff --git a/libs/dao/src/main/java/com/akto/dto/rbac/RbacEnums.java b/libs/dao/src/main/java/com/akto/dto/rbac/RbacEnums.java
index c0c8c7f2a4..d870cdbf5f 100644
--- a/libs/dao/src/main/java/com/akto/dto/rbac/RbacEnums.java
+++ b/libs/dao/src/main/java/com/akto/dto/rbac/RbacEnums.java
@@ -10,7 +10,9 @@ public enum AccessGroups {
         INVENTORY,
         TESTING,
         TEST_LIBRARY,
-        SETTINGS;
+        SETTINGS,
+        ADMIN,
+        USER;
     
         public static AccessGroups[] getAccessGroups() {
             return values();
@@ -22,7 +24,9 @@ public enum Feature {
         SENSITIVE_DATA(AccessGroups.INVENTORY),
         TRAFFIC_FILTERS(AccessGroups.INVENTORY),
         DEFAULT_PAYLOADS(AccessGroups.INVENTORY),
+        SAMPLE_DATA(AccessGroups.INVENTORY),
         TAGS(AccessGroups.INVENTORY),
+        ASK_GPT(AccessGroups.INVENTORY),
         START_TEST_RUN(AccessGroups.TESTING),
         TEST_RESULTS(AccessGroups.TESTING),
         TEST_ROLES(AccessGroups.TESTING),
@@ -34,8 +38,10 @@ public enum Feature {
         INTEGRATIONS(AccessGroups.SETTINGS),
         METRICS(AccessGroups.SETTINGS),
         LOGS(AccessGroups.SETTINGS),
-        BILLING(AccessGroups.SETTINGS);
-
+        BILLING(AccessGroups.SETTINGS),
+        INVITE_MEMBERS(AccessGroups.SETTINGS),
+        ADMIN_ACTIONS(AccessGroups.ADMIN),
+        USER_ACTIONS(AccessGroups.USER);
         private final AccessGroups accessGroup;
 
         Feature(AccessGroups accessGroup) {

From f797f625ddba05c4b2e37ee30d1bdcfdedcab567 Mon Sep 17 00:00:00 2001
From: Ark2307 <kr.aryan2307@gmail.com>
Date: Tue, 18 Jun 2024 09:15:05 +0530
Subject: [PATCH 10/24] Added access for user actions for each role

---
 .../main/java/com/akto/dto/rbac/DeveloperRoleStrategy.java | 1 +
 .../src/main/java/com/akto/dto/rbac/GuestRoleStrategy.java | 1 +
 .../main/java/com/akto/dto/rbac/MemberRoleStrategy.java    | 1 +
 libs/dao/src/main/java/com/akto/dto/rbac/RbacEnums.java    | 7 +++++++
 4 files changed, 10 insertions(+)

diff --git a/libs/dao/src/main/java/com/akto/dto/rbac/DeveloperRoleStrategy.java b/libs/dao/src/main/java/com/akto/dto/rbac/DeveloperRoleStrategy.java
index a63852145b..6bbc971d53 100644
--- a/libs/dao/src/main/java/com/akto/dto/rbac/DeveloperRoleStrategy.java
+++ b/libs/dao/src/main/java/com/akto/dto/rbac/DeveloperRoleStrategy.java
@@ -25,6 +25,7 @@ public Map<Feature, ReadWriteAccess> getFeatureAccessMap() {
                 accessMap.put(feature, access);
             }
         }
+        RbacEnums.mergeUserFeaturesAccess(accessMap);
         return accessMap;
     }
 }
diff --git a/libs/dao/src/main/java/com/akto/dto/rbac/GuestRoleStrategy.java b/libs/dao/src/main/java/com/akto/dto/rbac/GuestRoleStrategy.java
index 6314712684..c2bf625127 100644
--- a/libs/dao/src/main/java/com/akto/dto/rbac/GuestRoleStrategy.java
+++ b/libs/dao/src/main/java/com/akto/dto/rbac/GuestRoleStrategy.java
@@ -22,6 +22,7 @@ public Map<Feature, ReadWriteAccess> getFeatureAccessMap() {
                 accessMap.put(feature, access);
             }
         }
+        RbacEnums.mergeUserFeaturesAccess(accessMap);
         return accessMap;
     }
 }
diff --git a/libs/dao/src/main/java/com/akto/dto/rbac/MemberRoleStrategy.java b/libs/dao/src/main/java/com/akto/dto/rbac/MemberRoleStrategy.java
index d970e197b1..d632dd033b 100644
--- a/libs/dao/src/main/java/com/akto/dto/rbac/MemberRoleStrategy.java
+++ b/libs/dao/src/main/java/com/akto/dto/rbac/MemberRoleStrategy.java
@@ -25,6 +25,7 @@ public Map<Feature, ReadWriteAccess> getFeatureAccessMap() {
                 accessMap.put(feature, access);
             }
         }
+        RbacEnums.mergeUserFeaturesAccess(accessMap);
         return accessMap;
     }
 }
diff --git a/libs/dao/src/main/java/com/akto/dto/rbac/RbacEnums.java b/libs/dao/src/main/java/com/akto/dto/rbac/RbacEnums.java
index d870cdbf5f..cbe9f0b19b 100644
--- a/libs/dao/src/main/java/com/akto/dto/rbac/RbacEnums.java
+++ b/libs/dao/src/main/java/com/akto/dto/rbac/RbacEnums.java
@@ -2,6 +2,7 @@
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 public class RbacEnums {
@@ -63,4 +64,10 @@ public enum ReadWriteAccess {
         READ,
         READ_WRITE
     }
+
+    public static void mergeUserFeaturesAccess (Map<Feature, ReadWriteAccess> accessMap){
+        for(Feature feature: Feature.getFeaturesForAccessGroup(AccessGroups.USER)){
+            accessMap.put(feature, ReadWriteAccess.READ_WRITE);
+        }
+    }
 }

From 0a7b1fd4b03885f4eda76ddbceab59b810e11b05 Mon Sep 17 00:00:00 2001
From: Ark2307 <kr.aryan2307@gmail.com>
Date: Tue, 18 Jun 2024 09:58:41 +0530
Subject: [PATCH 11/24] fixing compilation errors

---
 apps/dashboard/src/main/resources/struts.xml             | 9 ++++-----
 .../src/apps/dashboard/pages/settings/users/Users.jsx    | 5 ++---
 2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/apps/dashboard/src/main/resources/struts.xml b/apps/dashboard/src/main/resources/struts.xml
index e0eed59d12..c319b57511 100644
--- a/apps/dashboard/src/main/resources/struts.xml
+++ b/apps/dashboard/src/main/resources/struts.xml
@@ -1725,10 +1725,6 @@
         <action name="api/createCollection" class="com.akto.action.ApiCollectionsAction" method="createCollection">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
-            <interceptor-ref name="usageInterceptor">
-                <param name="featureLabel">API_COLLECTIONS</param>
-            </interceptor-ref>
-            <result name="SUCCESS"  type="json">
             <interceptor-ref name="roleAccessInterceptor">
                 <param name="featureLabel">API_COLLECTIONS</param>
                 <param name="accessType">READ_WRITE</param>
@@ -1738,7 +1734,10 @@
                 <param name="ignoreHierarchy">false</param>
                 <param name="includeProperties">^actionErrors.*</param>
             </result>
-            </result>
+            <interceptor-ref name="usageInterceptor">
+                <param name="featureLabel">API_COLLECTIONS</param>
+            </interceptor-ref>
+            <result name="SUCCESS"  type="json"></result>
             <result name="ERROR" type="json">
                 <param name="statusCode">422</param>
                 <param name="ignoreHierarchy">false</param>
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
index 7e27a8e0d2..247bc1ac8c 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
@@ -1,5 +1,4 @@
-import AktoButton from './../../../components/shared/AktoButton';
-import { ActionList, Avatar, Banner, LegacyCard, Link, Page, Popover, ResourceItem, ResourceList, Text } from "@shopify/polaris"
+import { ActionList, Avatar, Banner, Button, LegacyCard, Link, Page, Popover, ResourceItem, ResourceList, Text } from "@shopify/polaris"
 import { DeleteMajor, TickMinor } from "@shopify/polaris-icons"
 import { useEffect, useState } from "react";
 import settingRequests from "../api";
@@ -180,7 +179,7 @@ const Users = () => {
                                         content: <Popover
                                                     active={roleSelectionPopup[id]}
                                                     onClose={() => toggleRoleSelectionPopup(id)}
-                                                    activator={<AktoButton disclosure onClick={() => toggleRoleSelectionPopup(id)}>{getRoleDisplayName(role)}</AktoButton>}
+                                                    activator={<Button disclosure onClick={() => toggleRoleSelectionPopup(id)}>{getRoleDisplayName(role)}</Button>}
                                                  >
                                                     <ActionList
                                                         actionRole="menuitem"

From 33800079a33ad03f81957b113baed1009aefcd58 Mon Sep 17 00:00:00 2001
From: Ark2307 <kr.aryan2307@gmail.com>
Date: Tue, 18 Jun 2024 12:22:52 +0530
Subject: [PATCH 12/24] added rbac role hierarchy in ui and backend

---
 .../main/java/com/akto/action/TeamAction.java | 79 +++++++++++++++----
 apps/dashboard/src/main/resources/struts.xml  | 24 +++++-
 .../src/apps/dashboard/pages/settings/api.js  |  9 +++
 .../dashboard/pages/settings/users/Users.jsx  | 34 ++++----
 .../src/main/java/com/akto/dao/RBACDao.java   | 16 ++++
 5 files changed, 131 insertions(+), 31 deletions(-)

diff --git a/apps/dashboard/src/main/java/com/akto/action/TeamAction.java b/apps/dashboard/src/main/java/com/akto/action/TeamAction.java
index 9b362623a0..2428882ca5 100644
--- a/apps/dashboard/src/main/java/com/akto/action/TeamAction.java
+++ b/apps/dashboard/src/main/java/com/akto/action/TeamAction.java
@@ -6,7 +6,6 @@
 import com.akto.dao.context.Context;
 import com.akto.dto.PendingInviteCode;
 import com.akto.dto.RBAC;
-import com.akto.dto.RBAC.Role;
 import com.akto.dto.User;
 import com.mongodb.BasicDBList;
 import com.mongodb.BasicDBObject;
@@ -75,30 +74,34 @@ public String fetchTeamData() {
 
     private enum ActionType {
         REMOVE_USER,
-        MAKE_ADMIN
+        UPDATE_USER_ROLE
     }
     
     String email;
-    public String performAction(ActionType action) {
+    public String performAction(ActionType action, String reqUserRole) {
         int currUserId = getSUser().getId();
         int accId = Context.accountId.get();
 
         Bson findQ = Filters.eq(User.LOGIN, email);
         User userDetails = UsersDao.instance.findOne(findQ);
         boolean userExists =  userDetails != null;
+
+        Bson filterRbac = Filters.and(
+            Filters.eq(RBAC.USER_ID, userDetails.getId()),
+            Filters.eq(RBAC.ACCOUNT_ID, accId));
+
         if (userExists && userDetails.getId() == currUserId) {
             addActionError("You cannot perform this action on yourself");
             return Action.ERROR.toUpperCase();
         }
 
+        RBAC.Role currentUserRole = RBACDao.getCurrentRoleForUser(currUserId, accId);
+        RBAC.Role userRole = RBACDao.getCurrentRoleForUser(userDetails.getId(), accId); // current role of the user whose role is changing
         switch (action) {
             case REMOVE_USER:
                 if (userExists) {
                     UsersDao.instance.updateOne(findQ, Updates.unset("accounts." + accId));
-                    RBACDao.instance.deleteAll(
-                            Filters.and(
-                                    Filters.eq(RBAC.USER_ID, userDetails.getId()),
-                                    Filters.eq(RBAC.ACCOUNT_ID, accId)));
+                    RBACDao.instance.deleteAll(filterRbac);
                     return Action.SUCCESS.toUpperCase();
                 } else {
                     DeleteResult delResult = PendingInviteCodesDao.instance.getMCollection().deleteMany(Filters.eq("inviteeEmailId", email));
@@ -109,14 +112,31 @@ public String performAction(ActionType action) {
                     }
                 }
 
-            case MAKE_ADMIN:
+            case UPDATE_USER_ROLE:
                 if (userExists) {
-                    RBACDao.instance.updateOne(
-                            Filters.and(
-                                    Filters.eq(RBAC.USER_ID, userDetails.getId()),
-                                    Filters.eq(RBAC.ACCOUNT_ID, accId)),
-                            Updates.set(RBAC.ROLE, Role.ADMIN));
-                    return Action.SUCCESS.toUpperCase();
+                    try {
+                        RBAC.Role[] rolesHierarchy = currentUserRole.getRoleHierarchy();
+                        boolean isValidUpdateRole = false;
+                        for(RBAC.Role role: rolesHierarchy){
+                            if(role == userRole){
+                                isValidUpdateRole = true;
+                                break;
+                            }
+                        }
+                        if(isValidUpdateRole){
+                            RBACDao.instance.updateOne(
+                                filterRbac,
+                                Updates.set(RBAC.ROLE, RBAC.Role.valueOf(reqUserRole)));
+                            return Action.SUCCESS.toUpperCase();
+                        }else{
+                            addActionError("User doesn't have access to modify this role.");
+                            return Action.ERROR.toUpperCase();
+                        }
+                    } catch (Exception e) {
+                        addActionError("User role doesn't exist.");
+                        return Action.ERROR.toUpperCase();
+                    }
+                    
                 } else {
                     addActionError("User doesn't exist");
                     return Action.ERROR.toUpperCase();
@@ -129,11 +149,30 @@ public String performAction(ActionType action) {
     }
 
     public String removeUser() {
-        return performAction(ActionType.REMOVE_USER);
+        return performAction(ActionType.REMOVE_USER, null);
     }
 
+    private String userRole;
+
     public String makeAdmin(){
-        return performAction(ActionType.MAKE_ADMIN);
+        return performAction(ActionType.UPDATE_USER_ROLE, userRole.toUpperCase());
+    }
+
+    private RBAC.Role[] userRoleHierarchy;
+
+    public String getRoleHierarchy(){
+        if(this.userRole == null || this.userRole.isEmpty()){
+            addActionError("Role cannot be null or empty");
+            return Action.ERROR.toUpperCase();
+        }
+        try {
+            RBAC.Role[] rolesHierarchy = RBAC.Role.valueOf(userRole).getRoleHierarchy();
+            this.userRoleHierarchy = rolesHierarchy;
+            return Action.SUCCESS.toUpperCase();
+        } catch (Exception e) {
+            addActionError("User role doesn't exist.");
+            return Action.ERROR.toUpperCase();
+        }
     }
 
     public int getId() {
@@ -160,4 +199,12 @@ public String getEmail() {
         return this.email;
     }
 
+    public void setUserRole(String userRole) {
+        this.userRole = userRole;
+    }
+
+    public RBAC.Role[] getUserRoleHierarchy() {
+        return userRoleHierarchy;
+    }
+
 }
diff --git a/apps/dashboard/src/main/resources/struts.xml b/apps/dashboard/src/main/resources/struts.xml
index c319b57511..efbb37f886 100644
--- a/apps/dashboard/src/main/resources/struts.xml
+++ b/apps/dashboard/src/main/resources/struts.xml
@@ -318,7 +318,7 @@
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
             <interceptor-ref name="roleAccessInterceptor">
-                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="featureLabel">USER_ACTIONS</param>
                 <param name="accessType">READ_WRITE</param>
             </interceptor-ref>
             <result name="FORBIDDEN" type="json">
@@ -334,6 +334,28 @@
             </result>
         </action>
 
+        <action name="api/getRoleHierarchy" class="com.akto.action.TeamAction" method="getRoleHierarchy">
+            <interceptor-ref name="json"/>
+            <interceptor-ref name="defaultStack" />
+            <interceptor-ref name="roleAccessInterceptor">
+                <param name="featureLabel">USER_ACTIONS</param>
+                <param name="accessType">READ_WRITE</param>
+            </interceptor-ref>
+            <result name="FORBIDDEN" type="json">
+                <param name="statusCode">403</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
+            <result name="SUCCESS"   type="json">
+                <param name="root">userRoleHierarchy</param>
+            </result>
+            <result name="ERROR" type="json">
+                <param name="statusCode">422</param>
+                <param name="ignoreHierarchy">false</param>
+                <param name="includeProperties">^actionErrors.*</param>
+            </result>
+        </action>
+
         <action name="signup-email" class="com.akto.action.SignupAction" method="registerViaEmail">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/api.js b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/api.js
index c31c3a7601..6cb0f21097 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/api.js
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/api.js
@@ -422,6 +422,15 @@ const settingRequests = {
             }
         });
     },
+    getRoleHierarchy(userRole){
+        return request({
+            url: '/api/getRoleHierarchy',
+            method: 'post',
+            data: {
+                userRole
+            }
+        });
+    }
 }
 
 export default settingRequests
\ No newline at end of file
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
index 247bc1ac8c..37aa61d829 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
@@ -20,6 +20,7 @@ const Users = () => {
 
     const [loading, setLoading] = useState(false)
     const [users, setUsers] = useState([])
+    const [roleHierarchy, setRoleHierarchy] = useState([])
 
     const [roleSelectionPopup, setRoleSelectionPopup] = useState({})
 
@@ -57,10 +58,19 @@ const Users = () => {
         }
     ]
 
+    const getRoleHierarchy = async() => {
+        const roleHierarchyResp = await settingRequests.getRoleHierarchy(window.USER_ROLE)
+        setRoleHierarchy(roleHierarchyResp)
+    }
+
+    useEffect(() => {
+        getTeamData();
+        getRoleHierarchy()
+    }, [])
+
     const handleRoleSelectChange = async (id, newRole, login) => {
         if(newRole === 'REMOVE') {
-            // await handleRemoveUser(login)
-            console.log("removing user ", login)
+            await handleRemoveUser(login)
             toggleRoleSelectionPopup(id)
             return
         }
@@ -68,7 +78,7 @@ const Users = () => {
         // Call Update Role API
         setUsers(users.map(user => user.login === login ? { ...user, role: newRole } : user))
         setRoleSelectionPopup(prevState => ({ ...prevState, [login]: false }))
-        console.log(newRole, login)
+        await updateUserRole(login, userRole)
 
         toggleRoleSelectionPopup(id)
     }
@@ -81,13 +91,14 @@ const Users = () => {
     }
 
     const getRolesOptionsWithTick = (currentRole) => {
-        return rolesOptions.map(section => ({
+        const tempArr =  rolesOptions.map(section => ({
             ...section,
-            items: section.items.map(item => ({
+            items: section.items.filter((c) => roleHierarchy.includes(c.role)).map(item => ({
                 ...item,
                 icon: item.role === currentRole ? TickMinor : item.icon
             }))
         }));
+        return tempArr
     }
 
     const getRoleDisplayName = (role) => {
@@ -108,12 +119,7 @@ const Users = () => {
         setLoading(false)
     };
 
-    useEffect(() => {
-        getTeamData();
-    }, [])
-
     const isLocalDeploy = false;
-    const currentUser = users.find(user => user.login === username)
 
     const toggleInviteUserModal = () => {
         setInviteUser({
@@ -129,9 +135,9 @@ const Users = () => {
         func.setToast(true, false, "User removed successfully")
     }
 
-    const handleMakeAdmin = async (login) => {
-        await settingRequests.makeAdmin(login)
-        func.setToast(true, false, "User " + login + " made admin successfully")
+    const updateUserRole = async (login,roleVal) => {
+        await settingRequests.makeAdmin(login, roleVal)
+        func.setToast(true, false, "Role updated for " + login + " successfully")
     }
     
     return (
@@ -173,7 +179,7 @@ const Users = () => {
                             const { id, name, login, role } = item;
                             const initials = func.initials(login)
                             const media = <Avatar user size="medium" name={login} initials={initials} />
-                            const shortcutActions = username !== login && role !== currentUser.role && currentUser.role !== "GUEST" ? 
+                            const shortcutActions = (username !== login && roleHierarchy.includes(role.toUpperCase())) ? 
                                 [
                                     {
                                         content: <Popover
diff --git a/libs/dao/src/main/java/com/akto/dao/RBACDao.java b/libs/dao/src/main/java/com/akto/dao/RBACDao.java
index 318ec61f20..4378859566 100644
--- a/libs/dao/src/main/java/com/akto/dao/RBACDao.java
+++ b/libs/dao/src/main/java/com/akto/dao/RBACDao.java
@@ -1,8 +1,11 @@
 package com.akto.dao;
 
 
+import org.bson.conversions.Bson;
+
 import com.akto.dao.context.Context;
 import com.akto.dto.RBAC;
+import com.akto.dto.RBAC.Role;
 import com.mongodb.client.model.Filters;
 
 public class RBACDao extends CommonContextDao<RBAC> {
@@ -46,6 +49,19 @@ public boolean isAdmin(int userId, int accountId) {
         return rbac != null && rbac.getAccountId() == accountId;
     }
 
+    public static Role getCurrentRoleForUser(int userId, int accountId){
+        Bson filterRbac = Filters.and(
+            Filters.eq(RBAC.USER_ID, userId),
+            Filters.eq(RBAC.ACCOUNT_ID, accountId));
+
+        RBAC userRbac = RBACDao.instance.findOne(filterRbac);
+        if(userRbac != null){
+            return userRbac.getRole();
+        }else{
+            return null;
+        }
+    }
+
     @Override
     public String getCollName() {
         return "rbac";

From fa954c748076b953d86b240452a33eaf3b12b409 Mon Sep 17 00:00:00 2001
From: Ark2307 <kr.aryan2307@gmail.com>
Date: Tue, 18 Jun 2024 13:05:09 +0530
Subject: [PATCH 13/24] fixing null pointer exception

---
 .../src/main/java/com/akto/action/TeamAction.java      |  2 +-
 .../web/src/apps/dashboard/pages/settings/api.js       |  5 +++--
 .../src/apps/dashboard/pages/settings/users/Users.jsx  | 10 +++-------
 3 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/apps/dashboard/src/main/java/com/akto/action/TeamAction.java b/apps/dashboard/src/main/java/com/akto/action/TeamAction.java
index 2428882ca5..58abda0713 100644
--- a/apps/dashboard/src/main/java/com/akto/action/TeamAction.java
+++ b/apps/dashboard/src/main/java/com/akto/action/TeamAction.java
@@ -155,7 +155,7 @@ public String removeUser() {
     private String userRole;
 
     public String makeAdmin(){
-        return performAction(ActionType.UPDATE_USER_ROLE, userRole.toUpperCase());
+        return performAction(ActionType.UPDATE_USER_ROLE, this.userRole.toUpperCase());
     }
 
     private RBAC.Role[] userRoleHierarchy;
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/api.js b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/api.js
index 6cb0f21097..4b0033f6b7 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/api.js
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/api.js
@@ -29,12 +29,13 @@ const settingRequests = {
             }
         })
     },
-    makeAdmin(email) {
+    makeAdmin(email, roleVal) {
         return request({
             url: '/api/makeAdmin',
             method: 'post',
             data: {
-                email: email
+                email: email,
+                userRole: roleVal
             }
         })
     },
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
index 37aa61d829..8019253863 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
@@ -1,4 +1,4 @@
-import { ActionList, Avatar, Banner, Button, LegacyCard, Link, Page, Popover, ResourceItem, ResourceList, Text } from "@shopify/polaris"
+import { ActionList, Avatar, Banner, Box, Button, Icon, LegacyCard, Link, Page, Popover, ResourceItem, ResourceList, Text } from "@shopify/polaris"
 import { DeleteMajor, TickMinor } from "@shopify/polaris-icons"
 import { useEffect, useState } from "react";
 import settingRequests from "../api";
@@ -30,22 +30,18 @@ const Users = () => {
             {
                 content: 'Admin',
                 role: 'ADMIN',
-                icon: <div style={{padding: "10px"}}/>
             },
             {
                 content: 'Security Engineer',
                 role: 'MEMBER',
-                icon: <div style={{padding: "10px"}}/>
             },
             {
                 content: 'Developer',
                 role: 'DEVELOPER',
-                icon: <div style={{padding: "10px"}}/>
             },
             {
                 content: 'Guest',
                 role: 'GUEST',
-                icon: <div style={{padding: "10px"}}/>
             }]
         },
         {
@@ -78,7 +74,7 @@ const Users = () => {
         // Call Update Role API
         setUsers(users.map(user => user.login === login ? { ...user, role: newRole } : user))
         setRoleSelectionPopup(prevState => ({ ...prevState, [login]: false }))
-        await updateUserRole(login, userRole)
+        await updateUserRole(login, newRole)
 
         toggleRoleSelectionPopup(id)
     }
@@ -95,7 +91,7 @@ const Users = () => {
             ...section,
             items: section.items.filter((c) => roleHierarchy.includes(c.role)).map(item => ({
                 ...item,
-                icon: item.role === currentRole ? TickMinor : item.icon
+                prefix: item.role === currentRole ? <Box><Icon source={TickMinor}/></Box> : <div style={{padding: "10px"}}/>
             }))
         }));
         return tempArr

From 257125134b2dd654c3e82311083518b98ffaeb20 Mon Sep 17 00:00:00 2001
From: Ark2307 <kr.aryan2307@gmail.com>
Date: Tue, 18 Jun 2024 13:29:51 +0530
Subject: [PATCH 14/24] added heirarchy in ui for invite user

---
 apps/dashboard/src/main/java/com/akto/action/TeamAction.java | 2 +-
 .../apps/dashboard/pages/settings/users/InviteUserModal.jsx  | 5 +++--
 .../web/src/apps/dashboard/pages/settings/users/Users.jsx    | 1 +
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/apps/dashboard/src/main/java/com/akto/action/TeamAction.java b/apps/dashboard/src/main/java/com/akto/action/TeamAction.java
index 58abda0713..e640f3c7b1 100644
--- a/apps/dashboard/src/main/java/com/akto/action/TeamAction.java
+++ b/apps/dashboard/src/main/java/com/akto/action/TeamAction.java
@@ -46,7 +46,7 @@ public String fetchTeamData() {
         for(Object obj: users) {
             BasicDBObject userObj = (BasicDBObject) obj;
             RBAC rbac = userToRBAC.get(userObj.getInt("id"));
-            String status = rbac == null ? "Member" : rbac.getRole().name();
+            String status = rbac == null ? "Guest" : rbac.getRole().name();
             userObj.append("role", status);
         }
 
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/InviteUserModal.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/InviteUserModal.jsx
index 91729ce3c8..a8f780ac80 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/InviteUserModal.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/InviteUserModal.jsx
@@ -5,7 +5,7 @@ import Store from "../../../store"
 import settingRequests from "../api"
 import Dropdown from "../../../components/layouts/Dropdown"
 
-const InviteUserModal = ({ inviteUser, setInviteUser, toggleInviteUserModal }) => {
+const InviteUserModal = ({ inviteUser, setInviteUser, toggleInviteUserModal, roleHierarchy }) => {
     const setToastConfig = Store(state => state.setToastConfig)
     const ref = useRef(null)
     const [inviteEmail, setInviteEmail] = useState()
@@ -62,6 +62,7 @@ const InviteUserModal = ({ inviteUser, setInviteUser, toggleInviteUserModal }) =
         func.copyToClipboard(inviteUser.inviteLink, ref, "Invitation link copied to clipboard")
     }
 
+    const filteredRoleOptions = rolesOptions.filter((c) => roleHierarchy.includes(c.value))
     if (inviteUser.state !== "success") {
         return (
             <Modal
@@ -96,7 +97,7 @@ const InviteUserModal = ({ inviteUser, setInviteUser, toggleInviteUserModal }) =
                     <Dropdown
                         id={"inviteRoleSelection"}
                         selected={handleRoleSelectChange}
-                        menuItems={rolesOptions} 
+                        menuItems={filteredRoleOptions} 
                         initial={inviteRole} />
 
                 </Modal.Section>
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
index 8019253863..3296eeea5b 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
@@ -227,6 +227,7 @@ const Users = () => {
                     inviteUser={inviteUser} 
                     setInviteUser={setInviteUser}
                     toggleInviteUserModal={toggleInviteUserModal}
+                    roleHierarchy={roleHierarchy}
                 />
             </div>
 

From f683775172e9004b1b675150f35298bdd59224ec Mon Sep 17 00:00:00 2001
From: shivamrawat101192 <shivam@akto.io>
Date: Tue, 18 Jun 2024 13:44:43 +0530
Subject: [PATCH 15/24] inviteeRole in PendingInviteCode and TeamAction

---
 .../com/akto/action/InviteUserAction.java     | 27 ++++++++++++++++--
 .../main/java/com/akto/action/TeamAction.java | 28 +++++++++++--------
 apps/dashboard/src/main/resources/struts.xml  |  1 +
 .../java/com/akto/dto/PendingInviteCode.java  | 18 ++++++++++++
 4 files changed, 60 insertions(+), 14 deletions(-)

diff --git a/apps/dashboard/src/main/java/com/akto/action/InviteUserAction.java b/apps/dashboard/src/main/java/com/akto/action/InviteUserAction.java
index 0a94d2ddb9..6f651e5b61 100644
--- a/apps/dashboard/src/main/java/com/akto/action/InviteUserAction.java
+++ b/apps/dashboard/src/main/java/com/akto/action/InviteUserAction.java
@@ -1,9 +1,11 @@
 package com.akto.action;
 
 import com.akto.dao.PendingInviteCodesDao;
+import com.akto.dao.RBACDao;
 import com.akto.dao.UsersDao;
 import com.akto.dao.context.Context;
 import com.akto.dto.PendingInviteCode;
+import com.akto.dto.RBAC;
 import com.akto.dto.User;
 import com.akto.notifications.email.SendgridEmail;
 import com.akto.util.DashboardMode;
@@ -28,6 +30,7 @@ public class InviteUserAction extends UserAction{
 
     public static final String INVALID_EMAIL_ERROR = "Invalid email";
     public static final String DIFFERENT_ORG_EMAIL_ERROR = "Email must belong to same organisation";
+    public static final String NOT_ALLOWED_TO_INVITE = "you're not authorised to invite for this role";
     public static final String AKTO_DOMAIN = "akto.io";
 
     public static String validateEmail(String email, String adminLogin) {
@@ -52,6 +55,7 @@ public static String validateEmail(String email, String adminLogin) {
     }
 
     private String finalInviteCode;
+    private RBAC.Role inviteeRole;
 
     @Override
     public String execute() {
@@ -65,6 +69,17 @@ public String execute() {
             return ERROR.toUpperCase();
         }
 
+        RBAC userRbac = RBACDao.instance.findOne(Filters.and(
+                Filters.eq(RBAC.USER_ID, user_id),
+                Filters.eq(RBAC.ACCOUNT_ID, Context.accountId.get())
+        ));
+
+        RBAC.Role userRole = userRbac.getRole();
+        if (!Arrays.asList(userRole.getRoleHierarchy()).contains(this.inviteeRole)) {
+            addActionError("User not allowed to invite for this role");
+            return ERROR.toUpperCase();
+        }
+
         Map<String,Object> claims = new HashMap<>();
         claims.put("email", inviteeEmail);
 
@@ -89,10 +104,8 @@ public String execute() {
         try {
             Jws<Claims> jws = JWT.parseJwt(inviteCode,"");
             PendingInviteCodesDao.instance.insertOne(
-                    new PendingInviteCode(inviteCode, user_id, inviteeEmail,jws.getBody().getExpiration().getTime(),Context.accountId.get())
+                    new PendingInviteCode(inviteCode, user_id, inviteeEmail,jws.getBody().getExpiration().getTime(),Context.accountId.get(), this.inviteeRole)
             );
-
-
         } catch (NoSuchAlgorithmException | InvalidKeySpecException | IOException e) {
             e.printStackTrace();
             return ERROR.toUpperCase();
@@ -138,4 +151,12 @@ public void setWebsiteHostName(String websiteHostName) {
     public String getFinalInviteCode() {
         return finalInviteCode;
     }
+
+    public RBAC.Role getInviteeRole() {
+        return inviteeRole;
+    }
+
+    public void setInviteeRole(RBAC.Role inviteeRole) {
+        this.inviteeRole = inviteeRole;
+    }
 }
diff --git a/apps/dashboard/src/main/java/com/akto/action/TeamAction.java b/apps/dashboard/src/main/java/com/akto/action/TeamAction.java
index e640f3c7b1..12d2e4f20a 100644
--- a/apps/dashboard/src/main/java/com/akto/action/TeamAction.java
+++ b/apps/dashboard/src/main/java/com/akto/action/TeamAction.java
@@ -6,6 +6,7 @@
 import com.akto.dao.context.Context;
 import com.akto.dto.PendingInviteCode;
 import com.akto.dto.RBAC;
+import com.akto.dto.RBAC.Role;
 import com.akto.dto.User;
 import com.mongodb.BasicDBList;
 import com.mongodb.BasicDBObject;
@@ -59,16 +60,22 @@ public String fetchTeamData() {
             if (pendingInviteCode.getAccountId() == 0) {//case where account id doesn't exists belonged to older 1_000_000 account
                 pendingInviteCode.setAccountId(1_000_000);
             }
+            Role inviteeRole = pendingInviteCode.getInviteeRole();
+            String roleText = "Invitation sent";
+            if (inviteeRole == null) {
+                roleText += "for Security Engineer";
+            } else {
+                roleText += "for " + inviteeRole.name();
+            }
             if (pendingInviteCode.getAccountId() == accountId) {
                 users.add(
                         new BasicDBObject("id", pendingInviteCode.getIssuer())
                                 .append("login", pendingInviteCode.getInviteeEmailId())
                                 .append("name", "-")
-                                .append("role", "Invitation sent")
+                                .append("role", roleText)
                 );
             }
         }
-
         return SUCCESS.toUpperCase();
     }
 
@@ -95,8 +102,8 @@ public String performAction(ActionType action, String reqUserRole) {
             return Action.ERROR.toUpperCase();
         }
 
-        RBAC.Role currentUserRole = RBACDao.getCurrentRoleForUser(currUserId, accId);
-        RBAC.Role userRole = RBACDao.getCurrentRoleForUser(userDetails.getId(), accId); // current role of the user whose role is changing
+        Role currentUserRole = RBACDao.getCurrentRoleForUser(currUserId, accId);
+        Role userRole = RBACDao.getCurrentRoleForUser(userDetails.getId(), accId); // current role of the user whose role is changing
         switch (action) {
             case REMOVE_USER:
                 if (userExists) {
@@ -115,9 +122,9 @@ public String performAction(ActionType action, String reqUserRole) {
             case UPDATE_USER_ROLE:
                 if (userExists) {
                     try {
-                        RBAC.Role[] rolesHierarchy = currentUserRole.getRoleHierarchy();
+                        Role[] rolesHierarchy = currentUserRole.getRoleHierarchy();
                         boolean isValidUpdateRole = false;
-                        for(RBAC.Role role: rolesHierarchy){
+                        for(Role role: rolesHierarchy){
                             if(role == userRole){
                                 isValidUpdateRole = true;
                                 break;
@@ -126,7 +133,7 @@ public String performAction(ActionType action, String reqUserRole) {
                         if(isValidUpdateRole){
                             RBACDao.instance.updateOne(
                                 filterRbac,
-                                Updates.set(RBAC.ROLE, RBAC.Role.valueOf(reqUserRole)));
+                                Updates.set(RBAC.ROLE, Role.valueOf(reqUserRole)));
                             return Action.SUCCESS.toUpperCase();
                         }else{
                             addActionError("User doesn't have access to modify this role.");
@@ -158,7 +165,7 @@ public String makeAdmin(){
         return performAction(ActionType.UPDATE_USER_ROLE, this.userRole.toUpperCase());
     }
 
-    private RBAC.Role[] userRoleHierarchy;
+    private Role[] userRoleHierarchy;
 
     public String getRoleHierarchy(){
         if(this.userRole == null || this.userRole.isEmpty()){
@@ -166,8 +173,7 @@ public String getRoleHierarchy(){
             return Action.ERROR.toUpperCase();
         }
         try {
-            RBAC.Role[] rolesHierarchy = RBAC.Role.valueOf(userRole).getRoleHierarchy();
-            this.userRoleHierarchy = rolesHierarchy;
+            this.userRoleHierarchy = Role.valueOf(userRole).getRoleHierarchy();
             return Action.SUCCESS.toUpperCase();
         } catch (Exception e) {
             addActionError("User role doesn't exist.");
@@ -203,7 +209,7 @@ public void setUserRole(String userRole) {
         this.userRole = userRole;
     }
 
-    public RBAC.Role[] getUserRoleHierarchy() {
+    public Role[] getUserRoleHierarchy() {
         return userRoleHierarchy;
     }
 
diff --git a/apps/dashboard/src/main/resources/struts.xml b/apps/dashboard/src/main/resources/struts.xml
index efbb37f886..9e4ebcf877 100644
--- a/apps/dashboard/src/main/resources/struts.xml
+++ b/apps/dashboard/src/main/resources/struts.xml
@@ -110,6 +110,7 @@
             </result>
         </action>
 
+<!--        //method for API does not exists-->
         <action name="api/createNewTeam" class="com.akto.action.TeamAction" method="saveNewTeam">
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
diff --git a/libs/dao/src/main/java/com/akto/dto/PendingInviteCode.java b/libs/dao/src/main/java/com/akto/dto/PendingInviteCode.java
index eaa7c7fb5a..4eeb3c7741 100644
--- a/libs/dao/src/main/java/com/akto/dto/PendingInviteCode.java
+++ b/libs/dao/src/main/java/com/akto/dto/PendingInviteCode.java
@@ -11,6 +11,7 @@ public class PendingInviteCode {
     private String inviteeEmailId;
     private long expiry;
     private int accountId;
+    private RBAC.Role inviteeRole;
 
     public PendingInviteCode() {
     }
@@ -21,8 +22,17 @@ public PendingInviteCode(String inviteCode, int issuer, String inviteeEmailId, l
         this.inviteeEmailId = inviteeEmailId;
         this.expiry = expiry;
         this.accountId = accountId;
+        this.inviteeRole = RBAC.Role.GUEST;
     }
 
+    public PendingInviteCode(String inviteCode, int issuer, String inviteeEmailId, long expiry, int accountId, RBAC.Role inviteeRole) {
+        this.inviteCode = inviteCode;
+        this.issuer = issuer;
+        this.inviteeEmailId = inviteeEmailId;
+        this.expiry = expiry;
+        this.accountId = accountId;
+        this.inviteeRole = inviteeRole;
+    }
     public ObjectId getId() {
         return id;
     }
@@ -70,4 +80,12 @@ public int getAccountId() {
     public void setAccountId(int accountId) {
         this.accountId = accountId;
     }
+
+    public RBAC.Role getInviteeRole() {
+        return inviteeRole;
+    }
+
+    public void setInviteeRole(RBAC.Role inviteeRole) {
+        this.inviteeRole = inviteeRole;
+    }
 }

From 7b98039efa45c4d93ea325ff367944193436acb4 Mon Sep 17 00:00:00 2001
From: shivamrawat101192 <shivam@akto.io>
Date: Tue, 18 Jun 2024 14:31:41 +0530
Subject: [PATCH 16/24] signup flow fix for invited roles

---
 .../main/java/com/akto/action/AccountAction.java    |  5 ++---
 .../src/main/java/com/akto/action/SignupAction.java | 13 ++++++++++---
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/apps/dashboard/src/main/java/com/akto/action/AccountAction.java b/apps/dashboard/src/main/java/com/akto/action/AccountAction.java
index 4da16dd73c..bdbdf93ace 100644
--- a/apps/dashboard/src/main/java/com/akto/action/AccountAction.java
+++ b/apps/dashboard/src/main/java/com/akto/action/AccountAction.java
@@ -268,16 +268,15 @@ public String createNewAccount() {
             }
         }
    
-        User user = initializeAccount(email, newAccountId, newAccountName,true);
+        User user = initializeAccount(email, newAccountId, newAccountName,true, RBAC.Role.ADMIN);
         getSession().put("user", user);
         getSession().put("accountId", newAccountId);
         return Action.SUCCESS.toUpperCase();
     }
 
-    public static User initializeAccount(String email, int newAccountId,String newAccountName,  boolean isNew) {
+    public static User initializeAccount(String email, int newAccountId, String newAccountName, boolean isNew, RBAC.Role role) {
         UsersDao.addAccount(email, newAccountId, newAccountName);
         User user = UsersDao.instance.findOne(eq(User.LOGIN, email));
-        RBAC.Role role = isNew ? RBAC.Role.ADMIN : RBAC.Role.MEMBER;
         RBACDao.instance.insertOne(new RBAC(user.getId(), role, newAccountId));
         Context.accountId.set(newAccountId);
         try {
diff --git a/apps/dashboard/src/main/java/com/akto/action/SignupAction.java b/apps/dashboard/src/main/java/com/akto/action/SignupAction.java
index 5db8592cee..b730a16f00 100644
--- a/apps/dashboard/src/main/java/com/akto/action/SignupAction.java
+++ b/apps/dashboard/src/main/java/com/akto/action/SignupAction.java
@@ -277,7 +277,7 @@ public String registerViaAuth0() throws Exception {
                 if(user != null){
                     AccountAction.addUserToExistingAccount(email, pendingInviteCode.getAccountId());
                 }
-                createUserAndRedirect(email, name, auth0SignupInfo, pendingInviteCode.getAccountId(), Config.ConfigType.AUTH0.toString());
+                createUserAndRedirect(email, name, auth0SignupInfo, pendingInviteCode.getAccountId(), Config.ConfigType.AUTH0.toString(), pendingInviteCode.getInviteeRole());
 
                 return SUCCESS.toUpperCase();
             } else if(pendingInviteCode == null){
@@ -367,6 +367,7 @@ public String registerViaEmail() {
             return ERROR.toUpperCase();
         }
         int invitedToAccountId = 0;
+        RBAC.Role inviteeRole = null;
         if (!invitationCode.isEmpty()) {
             Jws<Claims> jws;
             try {
@@ -393,6 +394,7 @@ public String registerViaEmail() {
             // deleting the invitation code
             PendingInviteCodesDao.instance.getMCollection().deleteOne(filter);
             invitedToAccountId = pendingInviteCode.getAccountId();
+            inviteeRole = pendingInviteCode.getInviteeRole();
         } else {
             if (!InitializerListener.isSaas) {
                 long countUsers = UsersDao.instance.getMCollection().countDocuments();
@@ -425,7 +427,7 @@ public String registerViaEmail() {
 
         try {
             shouldLogin = "true";
-            createUserAndRedirect(email, email, signupInfo, invitedToAccountId, "email");
+            createUserAndRedirect(email, email, signupInfo, invitedToAccountId, "email", inviteeRole);
         } catch (IOException e) {
             e.printStackTrace();
             return ERROR.toUpperCase();
@@ -690,6 +692,11 @@ public static String validatePassword(String password) {
 
     private void createUserAndRedirect(String userEmail, String username, SignupInfo signupInfo,
                                        int invitationToAccount, String method) throws IOException {
+        createUserAndRedirect(userEmail, username, signupInfo, invitationToAccount, method, null);
+    }
+
+    private void createUserAndRedirect(String userEmail, String username, SignupInfo signupInfo,
+                                       int invitationToAccount, String method, RBAC.Role invitedRole) throws IOException {
         User user = UsersDao.instance.findOne(eq("login", userEmail));
         if (user == null && "false".equalsIgnoreCase(shouldLogin)) {
             SignupUserInfo signupUserInfo = SignupDao.instance.insertSignUp(userEmail, username, signupInfo, invitationToAccount);
@@ -739,7 +746,7 @@ private void createUserAndRedirect(String userEmail, String username, SignupInfo
                 return;
             }
 
-            user = AccountAction.initializeAccount(userEmail, accountId, "My account",invitationToAccount == 0);
+            user = AccountAction.initializeAccount(userEmail, accountId, "My account",invitationToAccount == 0, invitedRole == null ? RBAC.Role.MEMBER : invitedRole);
 
             servletRequest.getSession().setAttribute("user", user);
             servletRequest.getSession().setAttribute("accountId", accountId);

From 2bc148a18035ee412253ec2353a27cc2b9fe7b87 Mon Sep 17 00:00:00 2001
From: Ark2307 <kr.aryan2307@gmail.com>
Date: Tue, 18 Jun 2024 15:13:18 +0530
Subject: [PATCH 17/24] fixing unit tests

---
 .../src/main/java/com/akto/action/ProfileAction.java |  6 ++----
 .../com/akto/action/testing/TestStartTestAction.java | 12 +++++++++++-
 .../web/src/apps/dashboard/pages/settings/api.js     |  2 +-
 .../pages/settings/users/InviteUserModal.jsx         |  3 ++-
 4 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/apps/dashboard/src/main/java/com/akto/action/ProfileAction.java b/apps/dashboard/src/main/java/com/akto/action/ProfileAction.java
index bbc2fc2ebb..623d188e96 100644
--- a/apps/dashboard/src/main/java/com/akto/action/ProfileAction.java
+++ b/apps/dashboard/src/main/java/com/akto/action/ProfileAction.java
@@ -113,9 +113,7 @@ public static void executeMeta1(Utility utility, User user, HttpServletRequest r
         String dashboardVersion = accountSettings.getDashboardVersion();
         String[] versions = dashboardVersion.split(" - ");
         User userFromDB = UsersDao.instance.findOne(Filters.eq(Constants.ID, user.getId()));
-        RBAC userRbac = RBACDao.instance.findOne(
-            Filters.eq(RBAC.USER_ID, user.getId())
-        );
+        RBAC.Role userRole = RBACDao.getCurrentRoleForUser(user.getId(), Context.accountId.get());
 
         boolean jiraIntegrated = false;
         try {
@@ -137,7 +135,7 @@ public static void executeMeta1(Utility utility, User user, HttpServletRequest r
                 .append("accountName", accountName)
                 .append("aktoUIMode", userFromDB.getAktoUIMode().name())
                 .append("jiraIntegrated", jiraIntegrated)
-                .append("userRole", userRbac.getRole().toString().toUpperCase());
+                .append("userRole", userRole.toString().toUpperCase());
 
         if (DashboardMode.isOnPremDeployment()) {
             userDetails.append("userHash", Intercom.getUserHash(user.getLogin()));
diff --git a/apps/dashboard/src/test/java/com/akto/action/testing/TestStartTestAction.java b/apps/dashboard/src/test/java/com/akto/action/testing/TestStartTestAction.java
index 02f00224b0..b955340680 100644
--- a/apps/dashboard/src/test/java/com/akto/action/testing/TestStartTestAction.java
+++ b/apps/dashboard/src/test/java/com/akto/action/testing/TestStartTestAction.java
@@ -4,6 +4,7 @@
 import com.akto.action.ApiTokenAction;
 import com.akto.dao.AccountSettingsDao;
 import com.akto.dao.ApiTokensDao;
+import com.akto.dao.RBACDao;
 import com.akto.dao.UsersDao;
 import com.akto.dao.billing.OrganizationsDao;
 import com.akto.dao.context.Context;
@@ -12,9 +13,11 @@
 import com.akto.dto.AccountSettings;
 import com.akto.dto.ApiInfo;
 import com.akto.dto.ApiToken;
+import com.akto.dto.RBAC;
 import com.akto.dto.User;
 import com.akto.dto.UserAccountEntry;
 import com.akto.dto.ApiToken.Utility;
+import com.akto.dto.RBAC.Role;
 import com.akto.dto.billing.Organization;
 import com.akto.dto.testing.*;
 import com.akto.dto.testing.TestingRun.State;
@@ -169,10 +172,17 @@ public void testStartCICDTest() throws IOException, ServletException {
         accountAccessMap.put(ACCOUNT_ID+"", userAccountEntry);
         
         User user = new User();
-        user.setLogin("test@akto.io");
+        String login="test@akto.io";
+        user.setLogin(login);
         user.setAccounts(accountAccessMap);
 
         UsersDao.instance.insertOne(user);
+
+        user = UsersDao.instance.findOne(Filters.eq(User.LOGIN, login));
+
+        RBAC rbac = new RBAC(user.getId(), Role.ADMIN, ACCOUNT_ID);
+        RBACDao.instance.insertOne(rbac);
+
         AccountSettings acc = new AccountSettings();
         acc.setDashboardVersion("test - test - test");
         acc.setId(ACCOUNT_ID);
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/api.js b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/api.js
index 4b0033f6b7..336c6cc345 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/api.js
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/api.js
@@ -9,7 +9,7 @@ const settingRequests = {
                 inviteeName: apiSpec.inviteeName,
                 inviteeEmail: apiSpec.inviteeEmail,
                 websiteHostName: apiSpec.websiteHostName,
-
+                inviteeRole: apiSpec.inviteeRole,
             }
         })
     },
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/InviteUserModal.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/InviteUserModal.jsx
index a8f780ac80..4430eab33b 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/InviteUserModal.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/InviteUserModal.jsx
@@ -36,7 +36,8 @@ const InviteUserModal = ({ inviteUser, setInviteUser, toggleInviteUserModal, rol
         const spec = {
             inviteeName: "there",
             inviteeEmail: inviteEmail,
-            websiteHostName: window.location.origin
+            websiteHostName: window.location.origin,
+            inviteeRole: inviteRole,
         }
 
         const inviteUsersResponse = await settingRequests.inviteUsers(spec)

From a471ece6dc41b01f205e64bfe68a50df2c6387a2 Mon Sep 17 00:00:00 2001
From: Ark2307 <kr.aryan2307@gmail.com>
Date: Thu, 20 Jun 2024 12:23:35 +0530
Subject: [PATCH 18/24] fixing unread status marking

---
 .../java/com/akto/action/testing_issues/IssuesAction.java  | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/apps/dashboard/src/main/java/com/akto/action/testing_issues/IssuesAction.java b/apps/dashboard/src/main/java/com/akto/action/testing_issues/IssuesAction.java
index ae56978489..c88aed1256 100644
--- a/apps/dashboard/src/main/java/com/akto/action/testing_issues/IssuesAction.java
+++ b/apps/dashboard/src/main/java/com/akto/action/testing_issues/IssuesAction.java
@@ -2,6 +2,7 @@
 
 import com.akto.action.ExportSampleDataAction;
 import com.akto.action.UserAction;
+import com.akto.dao.RBACDao;
 import com.akto.dao.context.Context;
 import com.akto.dao.demo.VulnerableRequestForTemplateDao;
 import com.akto.dao.test_editor.YamlTemplateDao;
@@ -9,6 +10,7 @@
 import com.akto.dao.testing.sources.TestSourceConfigsDao;
 import com.akto.dao.testing_run_findings.TestingRunIssuesDao;
 import com.akto.dto.ApiInfo;
+import com.akto.dto.RBAC.Role;
 import com.akto.dto.demo.VulnerableRequestForTemplate;
 import com.akto.dto.test_editor.Info;
 import com.akto.dto.test_editor.TestConfig;
@@ -167,6 +169,9 @@ public String fetchTestingRunResult() {
         if (issueId == null) {
             throw new IllegalStateException();
         }
+
+        Role currentUserRole = RBACDao.getCurrentRoleForUser(getSUser().getId(), Context.accountId.get());
+
         TestingRunIssues issue = TestingRunIssuesDao.instance.findOne(Filters.eq(ID, issueId));
         String testSubType = null;
         // ?? enum stored in db
@@ -182,7 +187,7 @@ public String fetchTestingRunResult() {
                 Filters.eq(TestingRunResult.API_INFO_KEY, issue.getId().getApiInfoKey())
         );
         testingRunResult = TestingRunResultDao.instance.findOne(filterForRunResult);
-        if (issue.isUnread()) {
+        if (issue.isUnread() && (currentUserRole.equals(Role.ADMIN) || currentUserRole.equals(Role.MEMBER))) {
             logger.info("Issue id from db to be marked as read " + issueId);
             Bson update = Updates.combine(Updates.set(TestingRunIssues.UNREAD, false),
                     Updates.set(TestingRunIssues.LAST_UPDATED, Context.now()));

From 39fd025a8864777c69ac70ed57b69b910e428b57 Mon Sep 17 00:00:00 2001
From: Ark2307 <kr.aryan2307@gmail.com>
Date: Thu, 20 Jun 2024 12:05:11 +0530
Subject: [PATCH 19/24] fixed feedbacks pt1

---
 .../interceptor/RoleAccessInterceptor.java     |  2 +-
 apps/dashboard/src/main/resources/struts.xml   |  6 +++---
 .../pages/settings/auth_types/AuthTypes.jsx    |  2 +-
 .../pages/settings/health_logs/Logs.jsx        | 18 +++++++++++++-----
 .../java/com/akto/dto/AccountSettings.java     |  2 +-
 libs/dao/src/main/java/com/akto/dto/RBAC.java  | 15 ++++++++++-----
 6 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java b/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java
index e3fd5fea89..76da0611f8 100644
--- a/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java
+++ b/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java
@@ -66,7 +66,7 @@ public String intercept(ActionInvocation invocation) throws Exception {
             }
             
             if(!hasRequiredAccess) {
-                ((ActionSupport) invocation.getAction()).addActionError("The role '" + userRole + "' does not have access.");
+                ((ActionSupport) invocation.getAction()).addActionError("The role '" + userRoleType.getName() + "' does not have access.");
                 return FORBIDDEN;
             }
         } catch(Exception e) {
diff --git a/apps/dashboard/src/main/resources/struts.xml b/apps/dashboard/src/main/resources/struts.xml
index 9e4ebcf877..1292b9392a 100644
--- a/apps/dashboard/src/main/resources/struts.xml
+++ b/apps/dashboard/src/main/resources/struts.xml
@@ -4269,7 +4269,7 @@
             <interceptor-ref name="defaultStack" />
             <interceptor-ref name="roleAccessInterceptor">
                 <param name="featureLabel">INTEGRATIONS</param>
-                <param name="accessType">READ_WRITE</param>
+                <param name="accessType">READ</param>
             </interceptor-ref>
 
             <result name="FORBIDDEN" type="json">
@@ -4879,7 +4879,7 @@
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
             <interceptor-ref name="roleAccessInterceptor">
-                <param name="featureLabel">ADMIN_ACTIONS</param>
+                <param name="featureLabel">METRICS</param>
                 <param name="accessType">READ_WRITE</param>
             </interceptor-ref>
 
@@ -4900,7 +4900,7 @@
             <interceptor-ref name="json"/>
             <interceptor-ref name="defaultStack" />
             <interceptor-ref name="roleAccessInterceptor">
-                <param name="featureLabel">ASK_GPT</param>
+                <param name="featureLabel">METRICS</param>
                 <param name="accessType">READ_WRITE</param>
             </interceptor-ref>
 
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/auth_types/AuthTypes.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/auth_types/AuthTypes.jsx
index 0c4eda99a5..c8b0d109a2 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/auth_types/AuthTypes.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/auth_types/AuthTypes.jsx
@@ -72,7 +72,7 @@ function AuthTypes() {
             items: [{
                 content: 'Edit',
                 onAction: () => navigate("details", { state: { name: item?.name, active: item?.active,
-                    headerConditions: item?.headerKeys, payloadConditions: item?.payloadKeys } }),
+                    headerConditions: item?.headerKeys, payloadConditions: item?.payloadKeys } })
             }]
         }]
     }
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/health_logs/Logs.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/health_logs/Logs.jsx
index d9850c2739..f3f6a4fb5a 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/health_logs/Logs.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/health_logs/Logs.jsx
@@ -1,9 +1,10 @@
-import { Button, ButtonGroup, HorizontalGrid, HorizontalStack, LegacyCard, Page, Scrollable, Select, Spinner, Text } from "@shopify/polaris"
+import { Button, ButtonGroup, LegacyCard, Text } from "@shopify/polaris"
 import { useEffect, useState } from "react";
 import settingRequests from "../api";
 import func from "@/util/func";
 import LogsContainer from "./LogsContainer";
 import Dropdown from "../../../components/layouts/Dropdown"
+import { saveAs } from 'file-saver'
 
 const Logs = () => {
     const fiveMins = 1000 * 60 * 5
@@ -15,6 +16,8 @@ const Logs = () => {
         logData: []
     })
     const [ loading, setLoading ] = useState(false)
+    const userRole = window.USER_ROLE
+    const disableButton = (userRole === "GUEST" || userRole === "DEVELOPER")
 
     const logGroupSelected = logs.logGroup !== ''
 
@@ -31,7 +34,6 @@ const Logs = () => {
     const fetchLogsFromDb = async (startTime, endTime, refresh = false) => {
         if (logs.logGroup !== '') {
             setLoading(true)
-
             const logsResponse = await settingRequests.fetchLogsFromDb(
                 Math.floor(startTime / 1000), 
                 Math.floor(endTime  / 1000),
@@ -53,7 +55,9 @@ const Logs = () => {
     useEffect(() => {
         const startTime = Date.now() - fiveMins
         const endTime = Date.now() 
-        fetchLogsFromDb(startTime, endTime)
+        if(!disableButton){
+            fetchLogsFromDb(startTime, endTime)
+        }
     }, [logs.logGroup])
 
    const exportLogsCsv = () => {
@@ -71,13 +75,17 @@ const Logs = () => {
     const handleRefresh = () => {
         const startTime = Date.now() - fiveMins;
         const endTime = Date.now();
-        fetchLogsFromDb(startTime, endTime, true)
+        if(!disableButton){
+            fetchLogsFromDb(startTime, endTime, true)
+        }
     }
 
     const handlePreviousFiveMinutesLogs = () => {
         const startTime = logs.startTime - fiveMins;
         const endTime = logs.startTime;
-        fetchLogsFromDb(startTime, endTime)
+        if(!disableButton){
+            fetchLogsFromDb(startTime, endTime)
+        }
     }
 
     return (
diff --git a/libs/dao/src/main/java/com/akto/dto/AccountSettings.java b/libs/dao/src/main/java/com/akto/dto/AccountSettings.java
index 6de5d55a20..e322c870d4 100644
--- a/libs/dao/src/main/java/com/akto/dto/AccountSettings.java
+++ b/libs/dao/src/main/java/com/akto/dto/AccountSettings.java
@@ -373,7 +373,7 @@ public List<String> getAllowRedundantEndpointsList() {
                 "mp4", "webm", "ogg", "ogv", "avi", "mov",  // Video formats
                 "mp3", "wav", "oga",  // Audio formats
                 "woff", "woff2", "ttf", "otf", // Font formats
-                ".pptx", ".json" // file formats
+                "pptx", "json" // file formats
             );
             return ignoreUrlTypesList;
         }
diff --git a/libs/dao/src/main/java/com/akto/dto/RBAC.java b/libs/dao/src/main/java/com/akto/dto/RBAC.java
index 28dd1510f5..b3c91c37ad 100644
--- a/libs/dao/src/main/java/com/akto/dto/RBAC.java
+++ b/libs/dao/src/main/java/com/akto/dto/RBAC.java
@@ -20,14 +20,15 @@ public class RBAC {
     public static final String ACCOUNT_ID = "accountId";
 
     public enum Role {
-        ADMIN(new AdminRoleStrategy()),
-        MEMBER(new MemberRoleStrategy()),
-        DEVELOPER(new DeveloperRoleStrategy()),
-        GUEST(new GuestRoleStrategy());
+        ADMIN("ADMIN",new AdminRoleStrategy()),
+        MEMBER("SECURITY ENGINEER", new MemberRoleStrategy()),
+        DEVELOPER("DEVELOPER", new DeveloperRoleStrategy()),
+        GUEST("GUEST", new GuestRoleStrategy());
 
         private final RoleStrategy roleStrategy;
+        private String name;
 
-        Role(RoleStrategy roleStrategy) {
+        Role(String name ,RoleStrategy roleStrategy) {
             this.roleStrategy = roleStrategy;
         }
 
@@ -38,6 +39,10 @@ public Role[] getRoleHierarchy() {
         public ReadWriteAccess getReadWriteAccessForFeature(Feature feature) {
             return roleStrategy.getFeatureAccessMap().getOrDefault(feature, ReadWriteAccess.READ);
         }
+
+        public String getName() {
+            return name;
+        }
     }
 
     public RBAC(int userId, Role role) {

From 99940c333ca56488c1f7dbaf6c0e175ed2fd3bd0 Mon Sep 17 00:00:00 2001
From: Ark2307 <kr.aryan2307@gmail.com>
Date: Fri, 21 Jun 2024 11:57:38 +0530
Subject: [PATCH 20/24] fixed ask gpt call

---
 apps/dashboard/src/main/resources/struts.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/apps/dashboard/src/main/resources/struts.xml b/apps/dashboard/src/main/resources/struts.xml
index 1292b9392a..fea167cae0 100644
--- a/apps/dashboard/src/main/resources/struts.xml
+++ b/apps/dashboard/src/main/resources/struts.xml
@@ -4838,7 +4838,7 @@
             <interceptor-ref name="defaultStack" />
             <interceptor-ref name="roleAccessInterceptor">
                 <param name="featureLabel">ASK_GPT</param>
-                <param name="accessType">READ_WRITE</param>
+                <param name="accessType">READ</param>
             </interceptor-ref>
 
             <result name="FORBIDDEN" type="json">

From 961131e93a8945d2e5617d9149d3b44bb0e59c0c Mon Sep 17 00:00:00 2001
From: Ark2307 <kr.aryan2307@gmail.com>
Date: Fri, 21 Jun 2024 13:10:01 +0530
Subject: [PATCH 21/24] fixing bugs

---
 .../apps/dashboard/pages/settings/health_logs/Logs.jsx | 10 ++++------
 .../apps/dashboard/pages/settings/metrics/Metrics.jsx  |  9 ++++++---
 apps/dashboard/web/polaris_web/web/src/util/func.js    |  4 ++++
 libs/dao/src/main/java/com/akto/dao/RBACDao.java       |  2 +-
 libs/dao/src/main/java/com/akto/dto/RBAC.java          |  1 +
 5 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/health_logs/Logs.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/health_logs/Logs.jsx
index f3f6a4fb5a..075f3ffac0 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/health_logs/Logs.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/health_logs/Logs.jsx
@@ -16,10 +16,8 @@ const Logs = () => {
         logData: []
     })
     const [ loading, setLoading ] = useState(false)
-    const userRole = window.USER_ROLE
-    const disableButton = (userRole === "GUEST" || userRole === "DEVELOPER")
-
     const logGroupSelected = logs.logGroup !== ''
+    const hasAccess = func.checkUserValidForIntegrations()
 
     const logGroupOptions = [
         { label: "Runtime", value: "RUNTIME" },
@@ -55,7 +53,7 @@ const Logs = () => {
     useEffect(() => {
         const startTime = Date.now() - fiveMins
         const endTime = Date.now() 
-        if(!disableButton){
+        if(hasAccess){
             fetchLogsFromDb(startTime, endTime)
         }
     }, [logs.logGroup])
@@ -75,7 +73,7 @@ const Logs = () => {
     const handleRefresh = () => {
         const startTime = Date.now() - fiveMins;
         const endTime = Date.now();
-        if(!disableButton){
+        if(hasAccess){
             fetchLogsFromDb(startTime, endTime, true)
         }
     }
@@ -83,7 +81,7 @@ const Logs = () => {
     const handlePreviousFiveMinutesLogs = () => {
         const startTime = logs.startTime - fiveMins;
         const endTime = logs.startTime;
-        if(!disableButton){
+        if(hasAccess){
             fetchLogsFromDb(startTime, endTime)
         }
     }
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/metrics/Metrics.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/metrics/Metrics.jsx
index a133ecc70b..22f173bea7 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/metrics/Metrics.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/metrics/Metrics.jsx
@@ -4,7 +4,6 @@ import DateRangeFilter from '../../../components/layouts/DateRangeFilter'
 import Dropdown from '../../../components/layouts/Dropdown'
 import {produce} from "immer"
 import func from '@/util/func'
-import Store from "../../../store"
 import "../settings.css"
 import settingFunctions from '../module'
 import GraphMetric from '../../../components/GraphMetric'
@@ -36,9 +35,13 @@ function Metrics() {
 
     const [menuItems,setMenuItems] =  useState(initialItems)
     const [groupBy, setGroupBy] = useState("ALL")
+    const hasAccess = func.checkUserValidForIntegrations()
 
     const getMetricsList = async() =>{
-        let arr = await settingFunctions.fetchMetricData()
+        let arr = []
+        if(hasAccess){
+            arr =  await settingFunctions.fetchMetricData()
+        }
         setMetricList(arr)
     }
     const names = ['INCOMING_PACKETS_MIRRORING','OUTGOING_PACKETS_MIRRORING','OUTGOING_REQUESTS_MIRRORING','TOTAL_REQUESTS_RUNTIME','FILTERED_REQUESTS_RUNTIME']
@@ -47,7 +50,7 @@ function Metrics() {
         
 
     const getGraphData = async(startTime,endTime) =>{
-        const metricData = await settingFunctions.fetchGraphData(groupBy,startTime,endTime,names,currentHost)
+        const metricData = hasAccess ? await settingFunctions.fetchGraphData(groupBy,startTime,endTime,names,currentHost) : []
         let result = {}
         for (const [key, countMap] of Object.entries(metricData)) {
             let val = func.convertTrafficMetricsToTrend(countMap)
diff --git a/apps/dashboard/web/polaris_web/web/src/util/func.js b/apps/dashboard/web/polaris_web/web/src/util/func.js
index 6e0ce035fb..7290c9314e 100644
--- a/apps/dashboard/web/polaris_web/web/src/util/func.js
+++ b/apps/dashboard/web/polaris_web/web/src/util/func.js
@@ -1484,6 +1484,10 @@ showConfirmationModal(modalContent, primaryActionContent, primaryAction) {
       return true;
     }
     return false;
+  },
+  checkUserValidForIntegrations(){
+    const userRole = window.USER_ROLE
+    return !(userRole === "GUEST" || userRole === "MEMBER")
   }
 }
 
diff --git a/libs/dao/src/main/java/com/akto/dao/RBACDao.java b/libs/dao/src/main/java/com/akto/dao/RBACDao.java
index 4378859566..add4acd1db 100644
--- a/libs/dao/src/main/java/com/akto/dao/RBACDao.java
+++ b/libs/dao/src/main/java/com/akto/dao/RBACDao.java
@@ -25,7 +25,7 @@ public void createIndicesIfAbsent() {
             clients[0].getDatabase(Context.accountId.get()+"").createCollection(getCollName());
         }
 
-        String[] fieldNames = {RBAC.USER_ID};
+        String[] fieldNames = {RBAC.USER_ID, RBAC.ACCOUNT_ID};
         MCollection.createIndexIfAbsent(getDBName(), getCollName(), fieldNames, true);
     }
 
diff --git a/libs/dao/src/main/java/com/akto/dto/RBAC.java b/libs/dao/src/main/java/com/akto/dto/RBAC.java
index b3c91c37ad..10ee815241 100644
--- a/libs/dao/src/main/java/com/akto/dto/RBAC.java
+++ b/libs/dao/src/main/java/com/akto/dto/RBAC.java
@@ -30,6 +30,7 @@ public enum Role {
 
         Role(String name ,RoleStrategy roleStrategy) {
             this.roleStrategy = roleStrategy;
+            this.name = name;
         }
 
         public Role[] getRoleHierarchy() {

From e8aec5bd7897d9ac07254a4b77b97a8ee46434a3 Mon Sep 17 00:00:00 2001
From: Ark2307 <kr.aryan2307@gmail.com>
Date: Fri, 21 Jun 2024 15:18:44 +0530
Subject: [PATCH 22/24] added paid feature functionality

---
 .../interceptor/RoleAccessInterceptor.java    | 28 +++++++++++++++++++
 .../pages/settings/users/InviteUserModal.jsx  | 18 ++++++------
 .../dashboard/pages/settings/users/Users.jsx  | 28 +++++++++++++------
 3 files changed, 55 insertions(+), 19 deletions(-)

diff --git a/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java b/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java
index 76da0611f8..0bcff4ae76 100644
--- a/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java
+++ b/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java
@@ -1,16 +1,24 @@
 package com.akto.interceptor;
 
 import com.akto.dao.RBACDao;
+import com.akto.dao.billing.OrganizationsDao;
+import com.akto.dto.RBAC;
 import com.akto.dto.User;
+import com.akto.dto.billing.FeatureAccess;
+import com.akto.dto.billing.Organization;
 import com.akto.dto.RBAC.Role;
+import com.akto.dto.rbac.RbacEnums;
 import com.akto.dto.rbac.RbacEnums.Feature;
 import com.akto.dto.rbac.RbacEnums.ReadWriteAccess;
+import com.akto.filter.UserDetailsFilter;
 import com.akto.log.LoggerMaker;
+import com.akto.util.DashboardMode;
 import com.mongodb.client.model.Filters;
 import com.opensymphony.xwork2.ActionInvocation;
 import com.opensymphony.xwork2.ActionSupport;
 import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
 
+import java.util.HashMap;
 import java.util.Map;
 
 public class RoleAccessInterceptor extends AbstractInterceptor {
@@ -31,17 +39,37 @@ public void setAccessType(String accessType) {
     public final static String FORBIDDEN = "FORBIDDEN";
     private final static String USER_ID = "userId";
     private final static String USER = "user";
+    private final static String FEATURE_LABEL_STRING = "RBAC_FEATURE";
 
+    private boolean checkForPaidFeature(int accountId){
+        if(!DashboardMode.isMetered()){
+            return false;
+        }
+        Organization organization = OrganizationsDao.instance.findOne(Filters.in(Organization.ACCOUNTS, accountId));
+        if(organization == null || organization.getFeatureWiseAllowed() == null || organization.getFeatureWiseAllowed().isEmpty()){
+            return false;
+        }
+
+        HashMap<String, FeatureAccess> featureWiseAllowed = organization.getFeatureWiseAllowed();
+        FeatureAccess featureAccess = featureWiseAllowed.getOrDefault(FEATURE_LABEL_STRING, FeatureAccess.noAccess);
+        return featureAccess.getIsGranted();
+    }
 
     @Override
     public String intercept(ActionInvocation invocation) throws Exception {
         try {
+
             if(featureLabel == null) {
                 throw new Exception("Feature list is null or empty");
             }
 
             Map<String, Object> session = invocation.getInvocationContext().getSession();
             User user = (User) session.get(USER);
+            int sessionAccId = (int) session.get(UserDetailsFilter.ACCOUNT_ID);
+
+            if(!(checkForPaidFeature(sessionAccId) || featureLabel.equalsIgnoreCase(RbacEnums.Feature.ADMIN_ACTIONS.toString()))){
+                return invocation.invoke();
+            }
 
             if(user == null) {
                 throw new Exception("User not found in session");
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/InviteUserModal.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/InviteUserModal.jsx
index 4430eab33b..0a76531778 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/InviteUserModal.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/InviteUserModal.jsx
@@ -5,18 +5,11 @@ import Store from "../../../store"
 import settingRequests from "../api"
 import Dropdown from "../../../components/layouts/Dropdown"
 
-const InviteUserModal = ({ inviteUser, setInviteUser, toggleInviteUserModal, roleHierarchy }) => {
+const InviteUserModal = ({ inviteUser, setInviteUser, toggleInviteUserModal, roleHierarchy, rolesOptions}) => {
     const setToastConfig = Store(state => state.setToastConfig)
     const ref = useRef(null)
     const [inviteEmail, setInviteEmail] = useState()
-    const [inviteRole, setInviteRole] = useState('GUEST')
-
-    const rolesOptions = [
-        {label: 'Guest', value: 'GUEST'},
-        {label: 'Admin', value: 'ADMIN'},
-        {label: 'Security engineer', value: 'MEMBER'},
-        {label: 'Developer', value: 'DEVELOPER'},
-    ]
+    const [inviteRole, setInviteRole] = useState('MEMBER')
 
     const handleRoleSelectChange = useCallback(
         (value) => {
@@ -63,7 +56,12 @@ const InviteUserModal = ({ inviteUser, setInviteUser, toggleInviteUserModal, rol
         func.copyToClipboard(inviteUser.inviteLink, ref, "Invitation link copied to clipboard")
     }
 
-    const filteredRoleOptions = rolesOptions.filter((c) => roleHierarchy.includes(c.value))
+    const filteredRoleOptions = rolesOptions[0].items.map((c) => {
+        return{
+            label: c?.content,
+            value: c?.role,
+        }
+    }).filter((c) => roleHierarchy.includes(c.value))
     if (inviteUser.state !== "success") {
         return (
             <Modal
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
index 3296eeea5b..302a7237d4 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
@@ -21,9 +21,26 @@ const Users = () => {
     const [loading, setLoading] = useState(false)
     const [users, setUsers] = useState([])
     const [roleHierarchy, setRoleHierarchy] = useState([])
+    const stiggFeatures = window.STIGG_FEATURE_WISE_ALLOWED
+    let rbacAccess = false;
+
+    if(stiggFeatures && stiggFeatures['RBAC_FEATURE']){
+        rbacAccess = stiggFeatures['RBAC_FEATURE'].isGranted
+    }
 
     const [roleSelectionPopup, setRoleSelectionPopup] = useState({})
 
+    let paidFeatureRoleOptions =  rbacAccess ? [
+        {
+            content: 'Developer',
+            role: 'DEVELOPER',
+        },
+        {
+            content: 'Guest',
+            role: 'GUEST',
+        }
+    ] : []
+
     const rolesOptions = [
         {
             items: [
@@ -34,15 +51,7 @@ const Users = () => {
             {
                 content: 'Security Engineer',
                 role: 'MEMBER',
-            },
-            {
-                content: 'Developer',
-                role: 'DEVELOPER',
-            },
-            {
-                content: 'Guest',
-                role: 'GUEST',
-            }]
+            }, {...paidFeatureRoleOptions}]
         },
         {
             items: [{
@@ -228,6 +237,7 @@ const Users = () => {
                     setInviteUser={setInviteUser}
                     toggleInviteUserModal={toggleInviteUserModal}
                     roleHierarchy={roleHierarchy}
+                    rolesOptions={rolesOptions}
                 />
             </div>
 

From 1252467004c1db79c4a262efa359babd2f97eac5 Mon Sep 17 00:00:00 2001
From: Ark2307 <kr.aryan2307@gmail.com>
Date: Sat, 22 Jun 2024 14:35:57 +0530
Subject: [PATCH 23/24] fixed ui for modals

---
 .../web/src/apps/dashboard/pages/settings/users/Users.jsx       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
index 302a7237d4..310e4c9fa0 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/users/Users.jsx
@@ -51,7 +51,7 @@ const Users = () => {
             {
                 content: 'Security Engineer',
                 role: 'MEMBER',
-            }, {...paidFeatureRoleOptions}]
+            }, ...paidFeatureRoleOptions]
         },
         {
             items: [{

From 999624c3b444aafce8cf11859c177461c8f30ca2 Mon Sep 17 00:00:00 2001
From: Aryan Khandelwal <60040654+Ark2307@users.noreply.github.com>
Date: Mon, 24 Jun 2024 13:04:33 +0530
Subject: [PATCH 24/24] Update RoleAccessInterceptor.java

---
 .../main/java/com/akto/interceptor/RoleAccessInterceptor.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java b/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java
index 0bcff4ae76..c8a28ff0d8 100644
--- a/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java
+++ b/apps/dashboard/src/main/java/com/akto/interceptor/RoleAccessInterceptor.java
@@ -47,7 +47,7 @@ private boolean checkForPaidFeature(int accountId){
         }
         Organization organization = OrganizationsDao.instance.findOne(Filters.in(Organization.ACCOUNTS, accountId));
         if(organization == null || organization.getFeatureWiseAllowed() == null || organization.getFeatureWiseAllowed().isEmpty()){
-            return false;
+            return true;
         }
 
         HashMap<String, FeatureAccess> featureWiseAllowed = organization.getFeatureWiseAllowed();