Overview
Standard Joget security often relies on broad role mapping. By using a custom BeanShell script, you can implement granular Screen Security that cross-references specific user roles against allowed screens stored in a database table. This ensures that even if a user has a general role, they only see functional screens (like Dashboards or Vendor Management) explicitly assigned to them.
How It Works
The script performs a real-time check against your Joget database (jwdb). It retrieves the roles assigned to the current user for the specific application and then verifies if any of those roles are authorized to view the requested "Screen Name" by querying a custom management table (app_fd_tbl_app_roles).
Where to Use in Joget
To implement this, follow these navigation paths within the Joget App Center:
-
💡 For Menu Visibility:
Userview Builder-->Select Menu Element-->Properties-->Permission-->BeanShell Permission -
💡 For Category Visibility:
Userview Builder-->Select Category-->Properties-->Permission-->BeanShell Permission -
💡 For Form Access:
Form Builder-->Properties-->Advanced-->Permission-->BeanShell Permission
Full Code
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.joget.commons.util.LogUtil;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
public boolean isUsernamePresent(String username) {
Collection roles = new ArrayList();
boolean access = false;
ResultSet resultSet = null;
Connection con = null;
String myDriver = "com.mysql.jdbc.Driver";
// Update port and DB name as per your environment
String myUrl = "jdbc:mysql://localhost:3307/jwdb?characterEncoding=UTF-8";
try {
Class.forName(myDriver);
con = DriverManager.getConnection(myUrl, "root", "");
String User = "#currentUser.username#";
String screenName = "Dashboard"; // Change this for each specific screen/menu
String AppID = "#appDef.appId#";
if(!con.isClosed()) {
PreparedStatement stmt = con.prepareStatement("SELECT c_roles FROM app_fd_tbl_app_user_role WHERE c_applicationId='"+AppID+"' and c_user = '"+User+"' and c_active='yes'");
resultSet = stmt.executeQuery();
while (resultSet.next()) {
String str = resultSet.getObject(1).toString();
String[] arr = str.split(";");
for(String text : arr) {
roles.add(text);
}
}
}
for (String role : roles) {
if (hasScreenInRole(role, screenName, con)) {
access = true;
break;
}
}
} catch (Exception e) {
LogUtil.error("Screen Security", e, "Error checking security for " + username);
} finally {
try {
if (resultSet != null) resultSet.close();
if (con != null) con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return access;
}
public boolean hasScreenInRole(String roleName, String screenName, Connection con) throws SQLException {
String sql = "SELECT COUNT(*) AS count FROM app_fd_tbl_app_roles WHERE c_roleName = ? AND c_screens like '%"+screenName+"%'";
PreparedStatement stmt = con.prepareStatement(sql);
stmt.setString(1, roleName);
ResultSet rs = stmt.executeQuery();
rs.next();
return rs.getInt("count") > 0;
}
// Admin bypass: Admins always see everything
String UserRole = "#currentUser.roles#";
return UserRole.contains("ROLE_ADMIN") ? true : isUsernamePresent("#currentUser.username#");
Example Use Cases
- 💡 Executive Dashboards: Restrict sensitive financial dashboards only to users with the "Finance_Lead" role.
- 💡 Vendor Portals: Ensure vendors only see the "Manage New Bid" screen if their specific account is active and mapped.
- 💡 Shared Portals: Control which business modules (e.g., HR vs. Procurement) appear in a single unified Userview.
Customization Tips
-
⚙️ Screen Names: Update the
screenNamevariable to match the specific menu item you are securing (e.g., "Manage New Bid"). -
⚙️ DB Credentials: Ensure the
myUrland database credentials match your local or server environment. -
⚙️ Database Table IDs: Ensure your custom management tables (
app_fd_tbl_app_user_roleandapp_fd_tbl_app_roles) are created and populated correctly.
Key Benefits
- ✅ Centralized Management: Manage permissions through a Joget form/table instead of hardcoding roles in the builder.
- ✅ Scalable Security: Easily add new screens or roles without needing to redeploy the application.
- ✅ Granular Visibility: Show or hide specific menus dynamically based on business logic.
Final Thoughts
Using BeanShell for screen-level security provides the flexibility required for complex enterprise applications. By guiding the logic through the Userview Builder --> Menu --> BeanShell path, you ensure that security is enforced at the very first point of user interaction.
Top comments (0)