Deny Editing based on attribute value

I want to deny edit operation based on ‘status’ attribute value. For example if status is ‘Closed’ then no role except admin can change the record.

I read about constraints but it is not based on roles.

I searched and doesn’t find info on such scenario.

Please advice

regards

Umesh

I made two access group admin and user and created constraint on user group to prevent editing record if status is ‘closed’ (allows when status is ‘assigned’). Now it is working fine.

but now there is separate issue. It allows user (user group) to edit the all attributes of record except ‘status’ when status is ‘Assigned’ and also not allowing to change the status in code as below from ‘Assigned’ to ‘closed’-

cm.setStatus(EnumStatus2.CLOSED);
cm.setClosedOn(today());
cm.setClosedBy(userSessionSource.getUserSession().getUser());
CommitContext commitContext = new CommitContext(cm);
dataManager.commit(commitContext);
btnClosed.setEnabled(false);

This is the constrain -

{E}.status == parse(com.company.sheelcompliance.entity.EnumStatus2.class, ‘ASSIGNED’)

I think it is due to check type of ‘check in memory’ for update operation type constraint. ‘Check in database’ is not available for update operation.

Any suggestions

regards

Umesh

Any suggestion please

Hi, Umesh!

If you want to use UserGroups and Constraints - you can use the following Groovy Script:

import com.haulmont.cuba.core.Persistence
import com.haulmont.cuba.core.global.AppBeans
Persistence persistence = AppBeans.get(Persistence.class)

return !(persistence.tools.getOldValue({E}, "status") in ("CLOSE"))

In this case if user with certain group will try to edit Order with «CLOSE» status - he will see «Access denied» message after clicking «OK» button at the editor screen.

Another way is to disable «Edit» button for all non-admin roles at the Browse screen for the Order entity, for example, like this:

@Inject
private Button editBtn;
@Inject
private CollectionContainer<Order> ordersDc;
@Inject
private UserSession userSession;

@Subscribe
private void onInit(InitEvent event) {
    ordersDc.addItemChangeListener(e -> {
        boolean isAdmin = false;
        for (UserRole userRole : userSession.getUser().getUserRoles()) {
            if ("Administrators".equals(userRole.getRole().getName())){
                isAdmin = true;
            }
        }

        editBtn.setEnabled(true);
        if (!isAdmin && StatusEnum.CLOSE.equals(e.getItem().getStatus())) {
            editBtn.setEnabled(false);
        }
    });
}

Welcome @chizhikov and thanks for reply

I tried first option but getting following error on testing the groovy script-

An error occurred while compiling Groovy script.

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: Script1.groovy: 2: unable to resolve class com.haulmont.cuba.core.Persistence @ line 2, column 1. import com.haulmont.cuba.core.Persistence ^ 1 error

In second option, double click on table also open edit screen. How to run same code on double click action on table?

I will prefer the first option because then it can be set as per client requirements on deployed app.

regards

Umesh

Prima facie solved by following this article from @mario , however still testing-

regards

Umesh

Hi, Umesh!

Please, test functionality of Groovy Script constraint without paying attention to the validation error.
Here is newly created issue due to such behavior: Error during GroovyScript constraint validation at access groups screen · Issue #2382 · cuba-platform/cuba · GitHub

Editor opening in case of double-click can be disabled the following way:

@Inject
private Button editBtn;
@Inject
private CollectionContainer<Order> ordersDc;
@Inject
private UserSession userSession;
@Inject
private GroupTable<Order> ordersTable;
@Named("ordersTable.edit")
private EditAction ordersTableEdit

@Subscribe
private void onInit(InitEvent event) {
    ordersDc.addItemChangeListener(e -> {
        editBtn.setEnabled(true);
        if (!isAdmin() && StatusEnum.CLOSE.equals(e.getItem().getStatus())) {
            editBtn.setEnabled(false);
        }
    });

    ordersTable.setItemClickAction(new BaseAction("tableClickAction") {
        @Override
        public void actionPerform(Component component) {
            if (isAdmin() || !StatusEnum.CLOSE.equals(ordersTable.getSingleSelected().getStatus())) {
                ordersTableEdit.actionPerform(ordersTable);
            }
        }
    });
}

protected boolean isAdmin() {
    for (UserRole userRole : userSession.getUser().getUserRoles()) {
        if ("Administrators".equals(userRole.getRole().getName())){
            return true;
        }
    }
    return false;
}

I checked the functionality again and it is working.

The groovy script from link was working perfectly without validation error or otherwise.

def dataManager = com.haulmont.cuba.core.global.AppBeans.get(com.haulmont.cuba.core.global.DataManager)
def currentPersistedEntity = dataManager.reload({E},"_local")
def closedStatus = parse(com.company.sheelcompliance.entity.EnumStatus2.class, ‘CLOSED’)

if ({E}.status != closedStatus) {
return true
}
else if (currentPersistedEntity.status != closedStatus && {E}.status == closedStatus) {
return true
}
else if (currentPersistedEntity.status == closedStatus && {E}.status != closedStatus) {
return true
}
else {
return false
}

I will check groovy script suggested by you again and come back. (Working, thanks, it is more compact and better way for this)
regards

Umesh

@chizhikov,

The solution suggested by you was working fine, but during testing today i found that id status is closed and I edit status from closed to assigned, it allowed this change.

It is totally confusing that at the time of editing other attribute it picks status perfectly but if you change status itself then it picks is wrongly.

Same is happening with @mario code also suggested in blog.

please advise

umesh