The Read Gate
OData in LaravelUi5 is read-only: writing goes through actions. Reading is gated by the Read ability. #[Read] on an entity set decides whether an actor may read the set at all. Which rows they then see is a separate question, answered by scoping.
Access does not gate OData
An app's #[Access] gates opening the app, not its OData endpoint. An entity set without #[Read] can be read by every signed-in partner. Gate every set that isn't meant for everyone.
Declaring it
Put #[Read] on the class the entity set is built from: a custom entity set, or the Eloquent model behind a discoverModel set.
use LaravelUi5\Sdk\Security\Attributes\Read;
#[Read('readInvoices', AcmeRole::Accounting, note: 'Read the invoice list.')]
final class InvoicesSet extends AbstractEntitySet
{
// …
}It takes the same three arguments as #[Access] and #[Act]: the ability, its role (declared with #[Role] on the module) and a note. The ability belongs to the app that exposes the set, and the set's OData name is its key. Run ui5:sync after adding it, then grant the role (Permission Levels).
What a denied read gets
| Request | Result |
|---|---|
| reading the gated set itself | 403, an OData error with the code read_forbidden |
$expand into a gated set | the expansion is dropped, the rest answers 200, and a sap-messages header says what was left out |
a $batch | each item is checked on its own |
The message reads "You are not authorized to read …", unless your translations define ui5.read_forbidden.
When it lets a read through
- The set has no
#[Read]. Sets are open unless gated. - The app gates no set at all.
- The request has no SDK context. Your
odata_middlewarebuilds that context withBindSdkContextForOData(Configuration). - The ability is declared but not synced yet. Until
ui5:synchas run, a new#[Read]does not lock anyone out, and it doesn't protect anything either. Sync with every deployment.
Read, then rows
| Layer | Decides | Where |
|---|---|---|
| Access | may the actor open the app or value help | when it is opened |
| Read | may the actor read this set | at the OData boundary |
| Rows | which rows the actor sees | in the set's query (Scoped Entity Sets) |
A value help carries #[Access] for opening it. The scopes it offers point at the Read ability of the set behind them.