6.5Bloom · UNot started

CDS access control (DCL)

Reading depth

What you'll learn

A DCL role puts row-level authorization inside the CDS model; #CHECK on the view requires a matching role, #NOT_REQUIRED skips it.

  • DCL moves row-level authorization into the model, replacing scattered AUTHORITY-CHECK.
  • Syntax: `define role ... { grant select on <view> where ( field ) = aspect pfcg_auth( ... ) }`.
  • `aspect pfcg_auth` maps a CDS field to a PFCG auth object and its fields.

In the Clean Core model, authorization moves *into* the data model. Instead of scattering AUTHORITY-CHECK statements through ABAP, you declare a Data Control Language (DCL) role — a separate object linked to a CDS view — that constrains which rows a user may read. The view becomes self-protecting: any consumer, whether Open SQL, OData or analytics, inherits the row-level filter automatically.

A DCL role reads `define role ... { grant select on <view> where ( field ) = aspect pfcg_auth( ... ) }`. The `aspect pfcg_auth` clause maps a view field to a classic PFCG authorization object and its fields, so the user's existing authorizations decide which rows pass. For example, granting select where `( companycode ) = aspect pfcg_auth( s_tcode, bukrs, actvt = '03' )` lets a user read only the company codes their authorization permits, with activity 03 (display).

The toggle that wires it together is the view annotation `@AccessControl.authorizationCheck`. Set to `#CHECK`, the view *requires* a matching DCL role — activation succeeds, but the first access errors at runtime if no role exists. Set to `#NOT_REQUIRED`, DCL is skipped entirely, which is appropriate for views you want readable from internal RAP queries that are not end-user-facing. Choosing the wrong value is a classic trap: `#CHECK` with no DCL compiles cleanly and fails only when someone reads the view.

Key points

  • DCL moves row-level authorization into the model, replacing scattered AUTHORITY-CHECK.
  • Syntax: `define role ... { grant select on <view> where ( field ) = aspect pfcg_auth( ... ) }`.
  • `aspect pfcg_auth` maps a CDS field to a PFCG auth object and its fields.
  • `@AccessControl.authorizationCheck: #CHECK` requires a matching DCL role.
  • `#NOT_REQUIRED` skips DCL — fine for internal, non-end-user-facing views.

Examples

A DCL role on an order view

Grants select only on the company codes the user's S_TCODE / BUKRS authorization permits, for display activity 03.

ABAP@EndUserText.label: 'Auth for Orders'
@MappingRole: true
define role ZI_OrderHeader_DCL {
  grant select on ZI_OrderHeader
    where ( CompanyCode ) = aspect pfcg_auth ( S_TCODE,
                                               BUKRS,
                                               ACTVT = '03' );
}

Source notes: clean-core-curriculum §6.5

Ask Claude

Build a prompt from this lesson + your question and open a fresh Claude chat with it pre-filled — handy for adapting a before/after pattern to your own object.