Decide whose records a visitor sees
Goal
Say once that the records in a table belong to the customer they name, so that every signed-in portal visitor sees their own and nobody else's — through every Custom API your portal uses, and through every one anybody adds later.
The problem it solves
Your portal reads through Custom APIs, and a script can already ask who is calling:
var mine = runQuery({
entity: 'par_ticket',
filter: { connector: 'And', conditions: [
{ field: 'par_customer', operator: 'Equals', value: portalCustomerId() }
]}
});
That works. It has worked since visitors could sign in. The trouble is that it has to be written again in every script, and it is invisible when it is missing: an API without that filter looks exactly like an API with it, returns rows perfectly happily, and shows one customer another customer's tickets.
A portal relationship rule moves that sentence out of the scripts and onto the table.
Before you start
- Your portal is set to People who sign in — see Ask visitors to sign in. A table with a relationship rule cannot be read by a portal anyone can open, because there would be nobody for its records to belong to.
- Your table has a field holding the customer — a lookup at Account is the usual shape, because that is what a visitor's company is.
- Your visitors are members of a customer. Somebody who signed up and has joined no company yet matches nothing at all, which is the safe answer and probably not the one you want them to see.
Steps
-
Open your solution and choose Data policies.
-
Press New and give it a name — Tickets belong to their customer.
-
Set Type to Whose records (portal).
-
Choose the table.
-
Write the condition:
Record.par_customer == Portal.CustomerIdIt is the platform's code editor, so a name it does not know, such as
Portal.CustomrId, is underlined while you type rather than refused when you save. -
Leave In force ticked, and press Save.
That is the whole feature. Nothing else has to be granted, referenced or switched on.
What you can compare against
Five things about the signed-in visitor, and the condition has to mention at least one of them — otherwise it is not saying whose records these are.
| What it is | |
|---|---|
Portal.CustomerId | The company they belong to. The one you will use nearly every time |
Portal.ContactId | Their own contact record, when they have one |
Portal.UserId | The portal user themselves |
Portal.Email | Their e-mail address |
Portal.Role | "Owner", "Billing" or "Member" at their company |
You can join conditions with && and ||, and compare the table's own fields as well:
Record.par_customer == Portal.CustomerId && Record.par_status != "Draft"
CurrentUser is not the visitorOn a portal, the "signed-in user" is the portal's own server — one identity shared by everybody
using it. That is why a relationship rule cannot read CurrentUser, and why an ordinary data policy
cannot read Portal. The screen refuses both when you save.
What it does, exactly
- Every read is narrowed, whichever Custom API asks. You can delete the filter from the scripts that have one; you do not have to.
- A create that would store a record against another customer is refused, against the record as it will actually be saved. So is an edit that would move one.
- A visitor who belongs to no company sees nothing — not the records whose customer is blank.
- One rule per table. If you need to replace one, write the new one with In force unticked, then swap them over.
What it does not do
It does not make the table private. Your own people, signed in to the platform, see what their security role lets them see, exactly as before. The rule is about portal visitors; it is not a substitute for granting a role access to records.
It is not granted to a role, and the screen will refuse you if you try. It belongs to the table. That is the point — a rule you have to remember to grant is a rule you can forget to grant.
Troubleshooting
"A portal relationship rule has to say which records belong to the visitor." Your condition
never mentions Portal. As written it is an ordinary filter, which is a different thing.
"…is already the portal relationship rule for…" One rule decides whose records a table holds. Switch the other one off, or edit it instead of adding a second.
A visitor sees nothing at all. Check they are a member of a customer, and that the field in your condition is the one actually holding the customer — a condition comparing the wrong field matches nothing rather than everything, deliberately.
The portal refuses to save with the table on its list. The portal is set to Anyone. A table whose records belong to a signed-in visitor needs a portal that has one.