Skip to content

Permissions and the SQL allowlist ​

There are two layers, and they decide different things.

Whether this menu can be opened comes from roles and menus. If the page cannot be opened, the next layer is never reached.

Which columns can be seen, which fields can be edited, and which buttons can be clicked after the page is open comes from three in-page permission tables. On the same page, roles can differ.

SQL allowlist ​

When a built-in page opens, the server scans the page JSON and puts every sql_id it finds into the session, under page:{page id}. Later /sql/run calls send X-Page-Id. An id that is not on the list is rejected.

An extension page reads sql_ids from index.json, under ext:{html path}. The request sends X-User-Ext-Entry. The HTML page has to be opened first. A direct call is rejected.

A popup child page needs both of these: its id is in the parent JSON SubPages, and the open carries from_page. Otherwise every SQL call from the child returns 403.

The development role (role_id 3) can send X-User-Id to act as someone else, and it can bypass the SQL allowlist. What you see with a development account is not what an ordinary user sees.

The three in-page tables ​

TableWhat it controlsProperties
sys.page_column_authGrid columnsvisible, allowEditing
sys.page_form_field_authForm fieldsvisible, allowEditing, readOnly
sys.page_action_authButtonsVisible, enabled

Each table has a role table. val is only 1 for explicitly allowed or -1 for explicitly denied. No row means the rule’s base_value applies.

page_id is the business page being configured. It is not the id of the configuration page itself.

Button names are the current capitalized names, for example Save, AddRow, and MainSelect. A permission expression written as "js:" in the page JSON is evaluated by the page. The configuration page does not take part.

If a column is visible: false but permissions or an expression still need its value, the column must set KeepData: true. See Page JSON.

This describes the platform. One customer’s business tables are not in these docs.