Hello Team,
can you please guide me on the right way to programatically filter the side menu items, i need to implement a logic where there are 3 categories of screens that can be presented to the same user, so ideally i want to have at the top of side menu 3 buttons when the user clicks them the side menu items should be refreshed and show the screens under the category selected.
You can already create the catagories by editing the Web Menu in Studio, I’m not sure I understand why you need to do anything to the menu programatically.
Hi Lewis,
Thanks for your reply. well, I think i know what you mean by categories, which is by creating new menu under web-menu. but unfortunately it won’t solve my issue. basically what i want to override is the code the draws the web-menu at runtime by adding 3 buttons at the top of the side menu called “employee self service”, “HR Admin” and “Country Admin” which represents the functional role the user is authorized to be. when the user clicks one of this buttons i want to refresh the side menu by including the screens relevant to the functional role he clicked on. the reason i want to do that is as following:
- when the user clicks one of the 3 buttons his user group will change and so is the records he is allowed to see in the screens.
- it will separate the screens completely in a logical way
- based on the first point (changing group) and if i didn’t hide the screens that belongs to another function and the user tries to open one of this screens, the screen will be empty because i changed the group which restricted the records retrieved by the to be hidden screen.
so also i would like a way to close all opened screens if the user wanted to change his functional role by clicking one of the 3 buttons.
i have an update after playing around a little bit, trying to dynamically change the group of the user; i now believe it’s not possible with the way i want it. simple because when you change the group you need to change the group constraints attached to the user session, which appears to be impossible after i read the manual because the user session object is built during during the login process and it’s copied and cached in the application tiers. so now i am trying to customize the login window and add this buttons to the login screen where the user has to choose the functional role he wants prior to login.
overriding the login screen and adding a lookupfield where the user selects his functional role and then changing the group of the user before logging in depending on the functional role selected works fine. my only issue now is how to filter the screens the user is authorized see. if any one knows how to filter the screens in the side menu please tell me.
1 Like
I Have found the complete solution that finally solved my requirements, I will recap what i want exactly for anyone who might have the same issue in the future:
Problem: some users might have 2 functional roles in the application, one role as an HR admin where he gets to see the records of all employees he is authorized to see and he needs to x number of screens. and the other functional role is as employee who he access different screen(s) and he only sees his own record. that type of users has been assigned roles that allow them to see the screens that belongs to HR admin role and employee role. i wanted this user to first identify his role prior to login.
solution:
1- I adjusted the login screen and included a checkbox where this type of users should select if they want to logon as employee, the code is as following:
public class ExtAppLoginWindow extends AppLoginWindow {
private static final Logger log = LoggerFactory.getLogger(AppLoginWindow.class);
@Inject
CheckBox isESS;
@Inject
AuthenticationService authenticationService;
@Inject
UserService userService;
@Override
public void init(Map<String, Object> params) {
super.init(params);
isESS.setValue(false);
}
private void changeUserGroup(User user, String groupName){
Group group = userService.getGroup(groupName);
userService.changeUserGroup(user, group);
}
@Override
public void doLogin() {
String login = loginField.getValue();
String password = passwordField.getValue() != null ? passwordField.getValue() : "";
if (StringUtils.isEmpty(login) || StringUtils.isEmpty(password)) {
showNotification(messages.getMainMessage("loginWindow.emptyLoginOrPassword"), NotificationType.WARNING);
return;
}
try {
Locale selectedLocale = localesSelect.getValue();
app.setLocale(selectedLocale);
User user;
if (loginByRememberMe && webConfig.getRememberMeEnabled()) {
user = authenticationService.authenticate(new RememberMeCredentials(login, password, selectedLocale)).getSession().getUser();
} else {
user = authenticationService.authenticate(new LoginPasswordCredentials(login, password, selectedLocale)).getSession().getUser();
}
boolean isAdmin = user.getUserRoles().stream().anyMatch(userRole -> userRole.getRole().getType() == RoleType.SUPER);
boolean isESS = userService.canBeAssignedToEmployee(user);
boolean isAppAdmin = userService.canBeAssignedToCountry(user) || userService.isAssignedToAnyOrganization(user);
boolean continueLogon = true;
if (isAdmin) {
changeUserGroup(user, "ROOT");
continueLogon = true;
} else if (isESS) {
if (!isAppAdmin) {
changeUserGroup(user, "ESS");
continueLogon = true;
} else {
if (this.isESS.isVisible()) {
if (this.isESS.isChecked()) {
changeUserGroup(user, "ESS");
} else {
changeUserGroup(user, "COMPANY_ADMIN");
}
continueLogon = true;
} else {
this.isESS.setVisible(true);
continueLogon = false;
showNotification("Please confirm your role, by either ticking the flag ESS and submit again to logon as employee or click submit again to logon as HR/Country Admin");
}
}
} else {
changeUserGroup(user, "COMPANY_ADMIN");
continueLogon = true;
}
if(continueLogon){
if (loginByRememberMe && webConfig.getRememberMeEnabled()) {
doLogin(new RememberMeCredentials(login, password, selectedLocale));
} else {
doLogin(new LoginPasswordCredentials(login, password, selectedLocale));
}
// locale could be set on the server
if (connection.getSession() != null) {
Locale loggedInLocale = connection.getSession().getLocale();
if (globalConfig.getLocaleSelectVisible()) {
app.addCookie(App.COOKIE_LOCALE, loggedInLocale.toLanguageTag());
}
}
}
} catch (InternalAuthenticationException e) {
log.error("Internal error during login", e);
showUnhandledExceptionOnLogin(e);
} catch (LoginException e) {
log.info("Login failed: {}", e.toString());
String message = StringUtils.abbreviate(e.getMessage(), 1000);
showLoginException(message);
} catch (Exception e) {
log.warn("Unable to login", e);
showUnhandledExceptionOnLogin(e);
}
}
}
2- i adjusted the main window screen to filter out unwanted menu items as following:
public class ExtAppMainWindow extends AbstractMainWindow {
@Inject
private FtsField ftsField;
@Inject
private Embedded logoImage;
@Inject
SideMenu sideMenu;
@Inject
UserSessionSource userSessionSource;
@Override
public void init(Map<String, Object> params) {
super.init(params);
initLayoutAnalyzerContextMenu(logoImage);
initLogoImage(logoImage);
initFtsField(ftsField);
Group group = userSessionSource.getUserSession().getUser().getGroup();
if(group.getName().equals("COMPANY_ADMIN")){
sideMenu.removeMenuItem(sideMenu.getMenuItem("employee-self-service"));
}
if(group.getName().equals("ESS")){
sideMenu.getMenuItems().forEach(menuItem -> {
if(!menuItem.getId().equals("employee-self-service")){
sideMenu.removeMenuItem(menuItem);
}
});
}
}
}