Permitted Sections from Company, Branch, Division, Department or Section

I have app based on database structure of companies:

  • Company One-to-Many Branch
  • Branch One-to-Many Division
  • Division One-to-Many Department
  • Department One-to-Many Section
  • Section One-to-Many Employee

An allowed_sections table (screen) allows users to select sections based on multiple rows in below columns:

  • User Not Nullable
  • Company Not Nullable
  • Branch Nullable
  • Division Nullable
  • Department Nullable
  • Section Nullable

User can add multiple rows like:

Table is shown in preview but not in actual question, attaching image of example data

Company has the widest whereas Section has the narrowest selection scope. For company C1 RowID 1, for C2 RowID 3 and for C3 RowID 5 will be effective selectors respectively. In essence, user can be allowed one or more companies, one or multiple branch(es) or only a particular section.

In screens, employees can be selected against permitted section(s) only. There will be section dropdown/pickup against which employees shall be populated. How can I setup constraints to populate only permitted sections? I am open to design change if someone can suggest something better.

Hi,

The task you describe is quite complex and hard to understand.

Do you want to restrict the data rows to be viewed globally by some users in the system, depending on the logged in user? This is a task of Access Groups: Constraints - CUBA Platform. Developer’s Manual

If you need just to restrict options in drop-down fields in some screens, based on another selected value on the screen, this can be coded manually in the screen, using DataLoadCoordinator: DataLoadCoordinator - CUBA Platform. Developer’s Manual

Hi @albudarov

Let me give you a few examples, suppose User1 user company wide permissions (Row1), User1 would be able to view employees from all the sections of all the departments of all divisions of all branches on employees browse screen and all the sections in the drop down in any edit screen where employee needs to be selected. User2 (Row3) has permission to only one. branch of a company, so on. sections of that branch will be visible in Sections drop down and employees of that branch will be visible in Employees browse. Things remain simple so far but User3 has permission to division DIV1 of branch B1 of company C1 and department DEPT2 of division DIV2 of branch B2 of company C2 (Row2 and Row4). Now in Sections drop down User3 should see sections of C1->B1->DIV1 and C2->B2->DIV2->DEPT2.

allowed_sections table can have multiple entries for any user. A user can have company wide access thus all sections of that company would be visible or to a specific section in which case only one section would be visible or to one division of a company, one department and one section in which case sections of department of specified division, sections of specified department and specified section should visible in Sections dropdown. Similarly, only employees of selected department should be visible in Employee browse screen.

Hi,
Well, this looks like requirements suitable for Access Groups.
Normally read access to entities is restricted by using a JPQL read constraint.

Your described requirements are quite complex. It would be hard to code them into one JPQL join + where clause.

So I would advise to implement the following:

  1. For every entity that needs to be constrainted, e.g. for Section, implement an auxiliary entity that serves only the purpose of storing accessibility information:
    E.g.
    @Entity
    class SectionAccessibility (
    UUID id,
    User user,
    Section section
    );

This entity should have an entry in the database for every combination of User and Section when particular User should have access to the corresponding Section. If no entry in database, then the pair is not accessible.

  1. Maintain entries of the auxiliary entities with the help of EntityChangedEvent handlers for the entities which participate in the accessibility conditions you’ve described.
    See info EntityChangedEvent - CUBA Platform. Developer’s Manual

These event handlers are where that complex logic of accessibility will be contained. On every creation change or deletion of related entities we need to recalculate accessibility rules and create or delete some SectionAccessibility entities.

  1. Then a JPQL read constraint can be written very simply and efficiently:
@AccessGroup(name = "Sales", parent = RootGroup.class)
public class FooGroup extends AnnotatedAccessGroupDefinition {

    @JpqlConstraint(target = Section.class, 
              join = ", SectionAccessibility sa", 
              where = "sa.section = {E} and sa.user.id = :session$userId") 
    @Override
    public ConstraintsContainer accessConstraints() {
        return super.accessConstraints();
    }
...
}

see info about access groups: Constraints - CUBA Platform. Developer’s Manual

This looks like the approach to address my issue. I will implement that in a few days and get back on this, hopefully marking your reply as Solution :slightly_smiling_face: :+1: