Can I implement @RowLevelRole for custom datastore entity?

Hi all,
I have a custom datastore that gets its data from a restful service. I am able to pull data for all the DTO entities perfectly. I have a requirement to restrict rows of salesorder data based on the businesspartner that login. The user entity has 1-1 relationship with businesspartner entity.

I have this rowlevelrole below that should do the demarcation. However, it does not work, The salesorder rows are displayed for all businesspartners

My question is: does @RowLevelRole work for custom datastore or not? If it does, why is the query below not working? Otherwise, what other way can Jmix handle this case scenario?

Thanks in advance.

@Nonnull
@RowLevelRole(name = "Business Partner Sales Orders", code = "business-partner-sales-order-role")
public interface BusinessPartnerSalesOrderRole {
    @JpqlRowLevelPolicy(entityClass = SalesOrder.class,
            where = "{E}.customerCode = :current_user_businessPartnerId)"
    )
    void BusinessPartnerSalesOrder();

Hi all,
Please assist with this request. I urgently need a solution to handle this scenario in my project whereby only the logged-in users can see their data. I am assuming @RoleLevelRole can work for this but it does not work. I was able to do it for Main store when the data is coming from database. But my project is entirely based on custom datastore- fetching data from a restful service.
My question is why it works for Main store but does not work for custom datastore using @RowLevelRole

Your quick assistance will be highly appreciated.

Thanks

Hi,

Row-level constraints are used by io.jmix.eclipselink.impl.JpaDataStore. If you create your own data store they won’t be applied. You will have to analyze accessConstraints that comes in the LoadContext instance to the loadList method of your custom data store explicitly.

JPQL policy doesn’t seem to be a good choice for your task because its purpose is to modify JPQL query, but as I understood you don’t query the database with JPQL, but use external REST service. Take a look at predicate policy.

You may read a bit about authorization mechanism in the documentation.

If I wanted to add row-level checks to the ProjectDatastore from the external-data-sample, I would do something like this:

    public List<Object> loadList(LoadContext<?> context) {
        MetaClass entityMetaClass = context.getEntityMetaClass();

        List<Project> projects = projectService.loadAll();

        InMemoryCrudEntityContext inMemoryCrudEntityContext = new InMemoryCrudEntityContext(entityMetaClass, applicationContext);
        accessManager.applyConstraints(inMemoryCrudEntityContext, context.getAccessConstraints());

        List<Project> filteredProjects = projects.stream()
                .filter(inMemoryCrudEntityContext::isReadPermitted)
                .collect(Collectors.toList());
        return new ArrayList<>(filteredProjects);
    }

Search for usages of io.jmix.core.accesscontext.InMemoryCrudEntityContext and io.jmix.core.accesscontext.CrudEntityContext in Jmix source code for better understanding how it works.

1 Like

Hi Gorbunkov,
Thanks for the information highlighted. I will work on it and revert.

Thanks

Hi Gorbunkov,
This works for me. I really appreciate your assistance.

Best regards