Mendix Rapid Developer study materials
Mendix Rapid Developer study resources

Dealer portal: entity access, XPath constraints and leaking order data

Mendix Rapid Developer · Put your knowledge to work in context.

All case studies

Dealer portal: entity access, XPath constraints and leaking order data

Northwind Parts runs a dealer portal. App security is set to Production. User roles DealerAdmin and DealerClerk are mapped to module roles in the Sales module. Order has entity access for both module roles with Create, Read, Update and Delete all ticked and no XPath constraint. The dashboard shows only the dealer's own orders because its microflow retrieves Order with the XPath constraint [Sales.Order_Dealer = $currentUser]. Yesterday a clerk opened a new All orders overview page that uses a data grid with an unconstrained database retrieve and saw 4,300 orders belonging to competing dealers, including prices. The team's plan is to add the XPath constraint to a microflow behind the page's search button and to hide the page from DealerClerk in the navigation. On the same page the Create order button does nothing for clerks and the log shows access-denied errors. Two Order attributes are read-only for DealerClerk, including the association to Dealer.

1. Evaluate the team's plan to fix the data leak. Where must row-level security actually live?

Read the worked answer

The plan does not fix the leak. Hiding a page in the navigation is cosmetic: the page remains in the client model and can be reached by URL. Putting the XPath constraint in the microflow behind the search button only constrains that one retrieve; any retrieve without a constraint, any data grid with a database source, and any future page still returns everything.

Row-level security belongs in entity access: add an XPath constraint on the Read rule of Order for DealerClerk, for example [Sales.Order_Dealer = '[%CurrentUser%]']. Mendix then applies the constraint to every retrieve of Order executed for a user in that role, in pages, microflows and published services alike. This is the only layer that is enforced by the runtime rather than by developer discipline.

Then layer the rest:

  • Keep the explicit XPath in microflows where you want a faster query or a different view, as defence in depth rather than as the only control.
  • Set the page visibility so honest users do not see irrelevant menus, knowing it is convenience, not security.
  • Remove Delete rights for DealerClerk if clerks should never delete orders.
  • Beware the administrator trap: a user with the Administrator role bypasses entity access, so test the leak with a real clerk account, not as an admin.

Finally, treat the incident as a data breach: log it, and re-test every page that queries Order.

2. Why does Create order fail for clerks when Create is ticked on the entity, and how does the read-only Dealer association make it worse?

Read the worked answer

Two access layers are in play and only one was checked.

  1. The button calls a microflow, and a microflow needs execute rights for the module role of the user. If no module role is granted execute on the creating microflow, the client gets access denied before a single object is created. Grant execute to the right module role, not to everyone.
  2. Even with execute rights, the create fails if the microflow writes a member the role cannot change. The Dealer association is read-only for DealerClerk, so the step that sets Order_Dealer to the current dealer violates entity access and throws.

The read-only association makes it worse in a subtler way. Suppose the microflow could create the order without setting the association. The new object would have an empty Order_Dealer, so the entity-access XPath constraint [Order_Dealer = current user] would exclude it immediately: the clerk creates an order and it vanishes from every list, looking like a save failure. Objects created under an XPath-constrained read rule must satisfy that constraint in the same transaction.

Correct fix: let a microflow running with system-level rights set the association (a microflow can be granted execute while the calling role keeps the association read-only), or make the association writable but constrain the selectable dealers. Then verify as a clerk: create, reopen, and confirm the order appears.

3. What else should be tightened before this portal goes back to dealers? Name the checks and the reasoning, not just the list.

Read the worked answer

Walk the model layer by layer, because a fix in one layer does not cover the others.

  • Module roles vs user roles. Confirm which module roles DealerAdmin and DealerClerk actually receive, and whether any user role accidentally aggregates both. A clerk who is also admin sees everything, and support will report the security as broken.
  • Every entity, not just Order. Dealer, PriceList, Invoice and any non-persistent entity used in a list need explicit access rules. Entities default to no access, but once someone ticks Read for convenience the leak returns. Non-persistent entities are not protected by entity access at all: guard them in the microflow that returns them.
  • Microflow and page access. Microflows default to no execute rights; pages to no visible roles. Check for microflows granted to Administrator only that ordinary flows call.
  • Published REST or OData services. They honour entity access for the calling user, but only if the service is not running as a fixed user. A service running with administrator credentials exposes everything, XPath constraints included.
  • Test with real accounts in each role, in acceptance, including a negative test that a clerk cannot read another dealer's order by manipulating the URL or the page's passing parameter.

Finally, ask why a two-dealer test was never run. Add a security test case to the definition of done for every page that retrieves a constrained entity.