Skip to main content

Roles

This screen manages NomaUBL's role-based access control. Each role bundles four kinds of grant:

  • A list of pages the role can reach (plus a list of dashboard cards visible to it).
  • A per-action whitelist of operations the role is allowed to perform (Edit, Delete, Resend, Push status…).
  • A data scope — the companies the role is restricted to and optional row filters that narrow the visible rows by column value.
  • The members assigned to the role.

Roles are application-wide and source-agnostic — they apply equally whether NomaUBL is plugged into JD Edwards, SAP, NetSuite or a custom ERP. Default roles (admin, viewer) are seeded by the Initialize Database action in Database Connectors → NomaUBL.

Refreshed in 2026.06.21

The editor has been reorganised around purpose-built tabs and the grant model now goes much finer than pages and read-only:

  • Four tabsAccess (pages, dashboard cards, features), Actions (the new per-button whitelist), Data scope (companies + row filters), Members. The role Name and Description sit above the tab bar so they stay visible from any tab.
  • Granular action permissions — the old all-or-nothing readonly flag is replaced by an explicit whitelist over Invoices, E-Reporting and Integration ops. A role with no whitelist set continues to allow every action (legacy behaviour); turning the whitelist on pre-populates with everything so the role does not suddenly lose actions.
  • Role-level row filters — pick a column (e.g. the invoice's customer alpha key UHALKY) and one or more values; the filter applies to the list views, the dashboard, every per-row endpoint and the rendered PDF stream. Multiple values on the same column are combined as OR; filters on different columns combine as AND, side-by-side with the existing Companies grant.
  • Per-card dashboard whitelist — each dashboard widget is its own permission. An empty list shows every card (existing behaviour); a populated list is a strict whitelist and hidden cards never run their SQL nor reach the wire.

Opening the editor

  • Sidebar → Configuration → Security → Roles.
  • The page opens with every existing role as a card. Click any card to expand the edit panel below the list. Use + New Role at the top right to start from scratch — the same edit panel opens with the Name field unlocked.

At a glance

Roles+ New RoleadminFull access — settings, all pages, all companies2 usersAdmin🗑customer_acmeExternal customer — only their own invoices (UHALKY = 123456)3 usersUser🗑operatorDay-to-day operations — no delete, no DB status push5 usersUser🗑DescriptionExternal customer — only their own invoices (UHALKY = 123456)🛡 Access✓ Actions🔎 Data scope👤 Members (3)Companies(empty list = all companies)00001×+ Add companyRow filters(empty = no row restriction — combined with Companies via AND)Invoices › Customer alpha keyUHALKY×123456×789012×+ Add value (OR)+ Add row filterEffective scopeCompany IN (00001) AND UHALKY IN (123456, 789012)SaveCancelCard listcopy / delete per roleFour tabsAccess · Actions · Data scope · MembersRow filtercolumn + values (OR); pairs offilters combine via ANDEffective scopelive preview of the AND/ORcombination written to F564254

Roles list

The top of the page lists every existing role as a card.

ElementDescription
NameInternal identifier of the role (e.g. admin, operator, customer_acme). Used to bind users to the role from the Users editor.
DescriptionFree-text human-readable summary.
Member countNumber of users currently assigned to the role.
BadgeAdmin when the role has the Settings access feature, User otherwise. Quick read of the role's reach.
⎘ CopyDuplicates the role: pre-fills the edit panel with all grants of the source role; the Name field is empty for the operator to choose a new one; the description gets (copy) appended.
🗑 DeleteRemoves the role after confirmation. Users assigned to it lose every permission until reassigned.

Click any card to open the Edit panel below the list. Use + New Role at the top right to create a role from scratch.


Identity (always visible)

The role's Name (visible only when creating) and Description sit above the tab bar, so the operator never has to switch tabs to relabel a role.

FieldDescription
NameInternal identifier of the role. Must be unique. Locked once created.
DescriptionHuman-readable summary shown in the role list.

Tab — Access

Defines what the role can reach: features, pages and dashboard cards.

Features

A short list of binary feature flags. Each row carries a checkbox plus a one-line helper that explains what the flag does.

FeatureHelper textEffect
Settings accessCan open the Settings page (template / connector editing).Opens the entire Configuration menu. The role is then displayed with the Admin badge in the list.
Read-only modeNo edit / delete / resend actions, even on permitted pages.Members can browse the application but every write action is disabled — overrides the Actions tab entirely.

Allowed Pages

A grouped checklist mirroring the application's left-hand navigation. Each page checkbox shows the friendly label (the same i18n nav.* key the Sidebar uses) plus the page id in muted monospace beside it — so the row stays informative when localised yet still searchable by id.

GroupPages
Navigationdashboard, techdashboard, invoices, vatdeclaration, ereporting, edirectory, notifications, integrationerrors, processinglog
Processingfetchinput, import, retrievestatuses
Operationsprocess, extractandprocess, processapi
UBLvalidate, xsleditor, xmlviewer, ubldefaults
Extractextractbip (JD Edwards-specific), extract, extractftp
Documentationreleasenotes, upgradehistory, statusreference, reasoncodes, ublreference, xref, apireference
Managementdocuments, pdftemplates, actions, notificationrules, dailydigest, autoretry, fileversions

Helpers:

  • All / None buttons above the groups — instantly grant or revoke every page.
  • Per-group check all / uncheck all toggle — flip an entire group in one click.
  • A group's checkbox shows an indeterminate state when only some of its pages are selected.
  • Empty list = all pages allowed. Same convention as the other lists: an unfiltered role sees everything.

Dashboard cards

Each dashboard widget is an individual permission keyed by dashboard.<card>. The grouping below mirrors the dashboard layout:

GroupCards
Hero metricsdashboard.total, dashboard.inflight, dashboard.errors-tech, dashboard.errors-business
Charts & widgetsdashboard.pipeline, dashboard.volume, dashboard.recent, dashboard.stale, dashboard.error-rules, dashboard.per-company, dashboard.ereporting, dashboard.round-trip
Sectionsdashboard.quick-actions
  • Empty list = every card visible (legacy behaviour).
  • A populated list is a strict whitelist — hidden cards are skipped server-side, so their SQL never runs and their data never reaches the wire.
  • The same All / None / per-group toggles are available as on the Allowed Pages list.

Tab — Actions

Defines what the role can do on the pages it can reach.

Restrict toggle

ToggleEffect
Off (default)Empty whitelist on the server — the role can perform every action allowed by its pages. Equivalent to the legacy behaviour.
OnOnly the actions checked below are allowed. Switching on pre-fills the list with every action so the role does not suddenly lose access — uncheck from there.

The helper text under the toggle states Off (default) = role can perform every action allowed by its pages. On = only the checked actions below are allowed.

The section header above the toggle reflects the current state:

  • (every action is allowed — no whitelist set) when the toggle is off.
  • (N actions explicitly allowed — everything else is blocked) when the toggle is on and N actions are checked.
  • (0 actions allowed — same effect as Read-only) when the whitelist is on but empty.
  • (Read-only mode is on under Access — every action is blocked) when the Read-only feature is on — the whole tab is greyed out.

Check all / Uncheck all buttons appear under the toggle (disabled when the whitelist is off).

Action catalog

Grouped by the page where the button lives — the same key can power buttons on more than one page.

GroupActionKeyEffect
InvoicesCreateinvoice.createDashboard Quick action and the New invoice button on the list.
InvoicesEditinvoice.editUpdate invoice fields from the detail modal / edit panel.
InvoicesDeleteinvoice.deleteHard-delete an invoice and all its child records.
InvoicesResend to PAinvoice.resendSubmit / re-submit an invoice (or a bulk batch) to the PA.
InvoicesPush status (PA)invoice.status.paSend a status event through the PA — payment received, in dispute, etc. (the Set Status modal's PA tab).
InvoicesPush status (DB)invoice.status.dbDirectly update a status in the database, bypassing the PA — admin break-fix path used when the PA round-trip is broken.
InvoicesValidate UBLinvoice.validateRun XSD + Schematron validation against the stored UBL XML (Validate button in the History tab).
InvoicesDownload UBLinvoice.downloadRead the raw UBL XML BLOB — the Download UBL button and the underlying /xml endpoint.
InvoicesPreset actionsinvoice.preset-actionUse the per-status preset buttons (Resend on 9904, …) in the seller actions row.
InvoicesCustom actionsinvoice.custom-actionUse the admin-defined custom buttons in the custom actions row.
InvoicesEmail PDFinvoice.emailSend the rendered PDF via the configured SMTP relay.
E-ReportingGenerate batchereporting.generateBuild a new e-reporting batch from the Generate dialog.
E-ReportingResend batchereporting.resendRe-submit an existing e-reporting batch to the PA.
Integration opsRun batch jobsintegration.runTrigger Import statuses / Fetch received / Retrieve statuses from the toolbar.
info

The detail modal renders Parties, Invoice Lines, TVA recap and Notes from the UBL XML endpoint, which is read-open (still subject to row filters and page visibility). Only the explicit Download UBL button is gated by invoice.download — view-only roles can therefore inspect the invoice content without the right to extract the raw XML.


Tab — Data scope

Defines which rows the role can see — companies and optional row filters.

Companies

An add-row table of company codes (KCO) the role is scoped to. Each row carries a free-form input and a × button to remove it; + Add company at the bottom appends a new row.

  • Empty list = all companies. This is the typical default — leaving the table empty grants the role access to every company in the database.
  • Adding even one row restricts the role to just the listed companies.
  • The placeholder hint reads KCO code (e.g. 00001) and the input uses a monospace font to make typos easier to spot.

Row filters

A more granular restriction: for any catalog column flagged as filterable, the role can be restricted to one or more exact values. Typical use case — an external customer who should only see invoices issued to its own alpha key (UHALKY).

Each row filter is a card with:

  1. A searchable column picker showing every filterable column across the four catalogs:
    • Invoices (header columns: UHALKY, UHAN8, customer name, contract reference, …).
    • Integration errors (the integration error catalog's row-filterable columns).
    • Processing log (processing-log catalog columns).
    • E-Reporting (e-reporting catalog columns).
  2. A list of values for the picked column, each on its own row with its own remove button. + Add value (OR) appends another value.
  3. A row-level remove button to drop the entire filter.

Below the list, + Add row filter lets a single role combine filters on different columns.

Combination rules

PatternCombined as
Multiple values on the same columnOR — the role sees rows that match any of the values.
Multiple columns in the filter listAND — the role sees only rows that match every column constraint.
Companies grant + row filtersAND — both must be satisfied.

Where row filters apply

A row filter is not a UI hint — it is enforced everywhere a forbidden row could otherwise leak:

  • The list views (Invoices, E-Reporting, Integration Errors, Processing Log) — the filter is appended to the SQL.
  • The Dashboard counters, charts and widgets — every card respects the role's row filter.
  • Per-row endpoints — lifecycle, lines, XML download, PDF render, status push, delete, resend, email PDF.
  • The rendered PDF byte stream — a forbidden row cannot even be turned into a PDF.

Forbidden rows return the same "not found" shape the UI uses for genuinely missing data, so the response cannot be used to probe for invoices a role should not know exist.


Tab — Members

Available only when editing an existing role (hidden during creation).

Lists every user currently bound to the role:

ColumnDescription
UsernameThe user's login.
Full nameThe user's display name (or when not set).
StatusActive (green) or Inactive (red).

This view is read-only — to add or remove a user from a role, edit the user from Configuration → Security → Users.


Save / Cancel

  • Create (when creating) / Save (when editing) persists the role and refreshes the list — available on every tab except Members.
  • Cancel discards changes and closes the panel.
  • Inline status messages appear below the panel (Role created, Role updated, Role deleted, error messages).

How grants are stored

Every grant is one row in F564254. The shape:

F564254
PMROLE — role name (FK to F564251.RLNAME)
PMCRAPPID — grant type: 'page' / 'company' / 'feature' / 'action'
/ 'dashboard-card' / 'row-filter'
PMCRAPPVAL — grant value, encoded per type:
page → page id (e.g. 'invoices')
company → KCO code (e.g. '00001')
feature → flag ('settings', 'readonly', 'actions-whitelist')
action → action key (e.g. 'invoice.delete')
dashboard-card → card key (e.g. 'dashboard.volume')
row-filter → 'column=value' (e.g. 'UHALKY=123456')
PMENABL — '1' enabled / '0' disabled (used during dialect-specific bootstrapping)

Row-filter grants are persisted as flat column=value strings — one row per (column, value) pair. The editor groups them by column on load and re-flattens them on save, so the operator never sees the raw shape.

Adding a future permission dimension becomes an INSERT in this same table — no DDL change required.

The bootstrap is idempotent: dropping F564254 and re-running Initialize Database re-seeds the default admin and viewer grants without touching role rows. The init log reports the count of newly-inserted grants for visibility.


Delete a role

Clicking the 🗑 icon on a role card opens a confirmation modal:

Delete role "X"? Users assigned to this role will lose their permissions.

Confirming removes the role and every grant row in F564254 keyed by it. Users previously bound to the role keep their account but lose every permission until they are reassigned to another role.


Tips & best practices

  • Create one role per profile, not per individual. operator, auditor, customer_<name> are simpler to maintain than per-user roles.
  • Grant Settings access sparingly. It opens the entire Configuration menu — limit it to a small admin group.
  • Pair Read-only with Actions off for compliance / audit accounts — both layers reinforce each other.
  • Use the Companies table to enforce multi-tenant isolation. Leaving it empty defeats company-level filtering for the role.
  • Row filters first, action whitelist second when scoping an external user. The row filter hides everything the user should not see; the action whitelist controls what they can do with what they see.
  • The dashboard card whitelist runs server-side — disabled cards never query the database. Use it to hide cost-sensitive widgets from low-trust roles.
  • Use Copy when forking a role. Starting from an existing role with one or two grants flipped is faster than rebuilding the checklists from scratch — and the result is closer to the source role's intent.
  • Re-run Initialize Database (Database Connectors → NomaUBL) if the default admin or viewer grants are missing — it re-seeds the rows without touching custom roles.
  • Delete a role only after re-binding its members. Once deleted, members lose access to everything until reassigned. The Members tab is the fastest way to check who would be affected.