Help for roles and permissions

Hi there,
I defined a new role by code and it works fine for Entities, Menu and Screens.

I need helpfor 2 specific task:

  1. Allow a user to change the password with the specific button (Additional popup).
  2. Allow the user to add, save, select, edit filters in a browse screen.

Many thanks in advance

Hi Luca,

You can create an input dialog and then use UserManager bean to change the password.
Below is a example of a screen with a button that invokes the dialog (the code is mostly copied from ChangePasswordAction class of the framework):

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<window xmlns="http://jmix.io/schema/ui/window"
        caption="msg://preferencesScreen.caption">
    <layout>
        <button id="changePasswordBtn" caption="Change password"/>
    </layout>
</window>
package com.company.app.screen.preferences;

import com.google.common.base.Strings;
import io.jmix.core.security.CurrentAuthentication;
import io.jmix.core.security.PasswordNotMatchException;
import io.jmix.core.security.UserManager;
import io.jmix.ui.Dialogs;
import io.jmix.ui.Notifications;
import io.jmix.ui.UiComponents;
import io.jmix.ui.app.inputdialog.DialogActions;
import io.jmix.ui.app.inputdialog.InputDialog;
import io.jmix.ui.app.inputdialog.InputParameter;
import io.jmix.ui.component.Button;
import io.jmix.ui.component.PasswordField;
import io.jmix.ui.component.ValidationErrors;
import io.jmix.ui.screen.*;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Objects;

@UiController("PreferencesScreen")
@UiDescriptor("preferences-screen.xml")
public class PreferencesScreen extends Screen {

    @Autowired
    private Dialogs dialogs;
    @Autowired
    private UiComponents uiComponents;
    @Autowired
    private UserManager userManager;
    @Autowired
    private Notifications notifications;
    @Autowired
    private CurrentAuthentication currentAuthentication;

    @Subscribe("changePasswordBtn")
    public void onChangePasswordBtnClick(Button.ClickEvent event) {
        Dialogs.InputDialogBuilder builder = dialogs.createInputDialog(this);

        builder.withCaption("Change password");

        PasswordField currentPasswField = uiComponents.create(PasswordField.class);
        currentPasswField.setCaption("Current password");
        currentPasswField.setWidthFull();

        PasswordField passwField = uiComponents.create(PasswordField.class);
        passwField.setCaption("New password");
        passwField.setWidthFull();

        PasswordField confirmPasswField = uiComponents.create(PasswordField.class);
        confirmPasswField.setCaption("Confirm password");
        confirmPasswField.setWidthFull();

        builder.withParameters(
                new InputParameter("currentPassword").withField(() -> currentPasswField),
                new InputParameter("password").withField(() -> passwField),
                new InputParameter("confirmPassword").withField(() -> confirmPasswField));

        builder.withValidator(validationContext -> getValidationErrors(passwField, confirmPasswField, validationContext));
        InputDialog inputDialog = builder.build();
        builder.withActions(DialogActions.OK_CANCEL, result -> okButtonAction(result));
        inputDialog.show();

    }

    private ValidationErrors getValidationErrors(PasswordField passwField, PasswordField confirmPasswField, InputDialog.ValidationContext validationContext) {
        String password = validationContext.getValue("password");
        String confirmPassword = validationContext.getValue("confirmPassword");
        ValidationErrors errors = new ValidationErrors();
        if (!Objects.equals(password, confirmPassword)) {
            errors.add(confirmPasswField, "Passwords do not match");
        }
        if (Strings.isNullOrEmpty(password)) {
            errors.add(passwField, "Password required");
        }
        if (errors.isEmpty()) {
            return ValidationErrors.none();
        }
        return errors;
    }

    private void okButtonAction(InputDialog.InputDialogResult result) {
        String userName = currentAuthentication.getUser().getUsername();

        if (result.getCloseActionType() == InputDialog.InputDialogResult.ActionType.OK) {
            String newPassword = result.getValue("password");
            String oldPassword = result.getValue("currentPassword");
            try {
                userManager.changePassword(userName, oldPassword, newPassword);
            } catch (PasswordNotMatchException e) {
                notifications.create()
                        .withType(Notifications.NotificationType.ERROR)
                        .withCaption("Wrong current password")
                        .show();
                return;
            }
            notifications.create()
                    .withType(Notifications.NotificationType.HUMANIZED)
                    .withCaption("Password changed")
                    .show();
        }
    }
}

To enable this screen for all users, include appropriate permissions to their role.

Add UiFilterRole role to your users.

In a design-time role definition, just add it to the extends clause:

package com.company.app.security;

import io.jmix.security.role.annotation.ResourceRole;
import io.jmix.securityui.role.UiFilterRole;
import io.jmix.securityui.role.UiMinimalRole;
import io.jmix.securityui.role.annotation.MenuPolicy;
import io.jmix.securityui.role.annotation.ScreenPolicy;

@ResourceRole(name = "UsersRole", code = "users-role", scope = "UI")
public interface UsersRole extends UiMinimalRole, UiFilterRole {
    // ...
}

In the runtime roles management, add UI: edit filters role as a child role to your users role.

Regards,
Konstantin

1 Like

Thanks a lot for your prompt reply.

it worked but…

the only thing that does not work is the “Make default
I mean it does not show any error but closing and opening again the form it does not remember the default filters.

Ok, I was able to make it work.
I’m not sure which attribute is the right one but Allowing the items in the picture Jmix remember the default filter for the entity/user.

Thanks for your time and for your beautiful job

Hello!

There are no specific permissions to make filter configuration default. I’ve tried to reproduce the issue on the 1.0.0 version without the success, filter remembers the default. Could you reproduce it on a small demo project or provide steps about how to reproduce the issue?

You can find a description of filter specific permissions in the documentation.

  • To create/change/delete filter configurations, users must have the ui.filter.modifyConfiguration specific permission.

  • To create/change/delete global (available for all users) filter configurations, users must have the ui.filter.modifyGlobalConfiguration specific permission.

  • To create/change JPQL conditions in run-time, users must have the ui.filter.modifyJpqlCondition specific permission.

You’re right.
I tried to reproduce the “default problem” doing the same things than before but it works fine without any other permission.
Good to know. I’m sorry you have lost time on it.