diff --git a/docs/.vitepress/playground.mjs b/docs/.vitepress/playground.mjs index c0aa9ba6..e75b3079 100644 --- a/docs/.vitepress/playground.mjs +++ b/docs/.vitepress/playground.mjs @@ -105,6 +105,16 @@ const NEEDS_MORE_THAN_A_BROWSER = [ why: 'calls a function module, and there is no application server to call one on', what: /\bCALL\s+FUNCTION\b/i, }, + { + /* Not a transpiler question - whatever AUTHORITY-CHECK compiles to, the + * page in the browser has no user, no roles and no authorization objects, + * so sy-subrc after it means nothing. An example whose whole point is + * which branch the check takes cannot take either one here. Reasoned + * rather than watched, unlike the lines above it, and it fails towards no + * button like the rest. */ + why: 'runs an authority check, and the browser has no user and no roles for one', + what: /\bAUTHORITY-CHECK\b/i, + }, ]; /* diff --git a/docs/advanced/extensibility/custom_control.md b/docs/advanced/extensibility/custom_control.md index f208534b..4a55e723 100644 --- a/docs/advanced/extensibility/custom_control.md +++ b/docs/advanced/extensibility/custom_control.md @@ -29,8 +29,8 @@ view->ele( n = `View` ns = `mvc` )->a( n = `onEvent` v = client->_event( `MY_EVENT` ) ). ``` -The wrapper class the previous builder needed for this -([`z2ui5_cl_xml_view_cc`](https://github.com/abap2UI5/abap2UI5/blob/main/src/99/z2ui5_cl_xml_view_cc.clas.abap)) -is frozen along with the builder itself, and adding a method to it is no longer -part of shipping a custom control. +Nothing else is needed on the ABAP side. The builder writes whatever element +and namespace you pass, verbatim, so a custom control is just another tag — +there is no wrapper class to extend and no method to add before it can be +used. diff --git a/docs/advanced/extensibility/user_exits.md b/docs/advanced/extensibility/user_exits.md index 37179ef4..19ead5ce 100644 --- a/docs/advanced/extensibility/user_exits.md +++ b/docs/advanced/extensibility/user_exits.md @@ -3,7 +3,7 @@ outline: [2, 4] --- # User Exits -abap2UI5 offers predefined user exits for tweaking the standard behavior. The interface [`Z2UI5_IF_EXIT`](https://github.com/abap2UI5/abap2UI5/blob/main/src/99/z2ui5_if_exit.intf.abap) exposes the user exits. To use them on your system, build a class that implements the interface and its methods. The abap2UI5 class [`Z2UI5_CL_UI5_USER_EXIT`](https://github.com/abap2UI5/abap2UI5/blob/main/src/01/04/z2ui5_cl_ui5_user_exit.clas.abap) calls them dynamically. Put your class in a custom package — **not** in the abap2UI5 packages. +abap2UI5 offers predefined user exits for tweaking the standard behavior. The interface [`Z2UI5_IF_UI5_EXIT`](https://github.com/abap2UI5/abap2UI5/blob/main/src/02/z2ui5_if_ui5_exit.intf.abap) exposes the user exits. To use them on your system, build a class that implements the interface and its methods. The abap2UI5 class [`Z2UI5_CL_UI5_USER_EXIT`](https://github.com/abap2UI5/abap2UI5/blob/main/src/01/04/z2ui5_cl_ui5_user_exit.clas.abap) calls them dynamically. Put your class in a custom package — **not** in the abap2UI5 packages. The interface exposes two exit methods: - **`set_config_http_get`** — called on the initial HTTP GET request (page load). Use it to set frontend properties like the UI5 theme, the UI5 version, or the inline CSS. @@ -15,19 +15,19 @@ Both methods take a `cs_config` changing parameter whose fields you can set as n CLASS zcl_a2ui5_user_exit DEFINITION PUBLIC. PUBLIC SECTION. - INTERFACES z2ui5_if_exit. + INTERFACES z2ui5_if_ui5_exit. ENDCLASS. CLASS zcl_a2ui5_user_exit IMPLEMENTATION. - METHOD z2ui5_if_exit~set_config_http_get. + METHOD z2ui5_if_ui5_exit~set_config_http_get. cs_config-theme = `sap_belize`. ENDMETHOD. - METHOD z2ui5_if_exit~set_config_http_post. + METHOD z2ui5_if_ui5_exit~set_config_http_post. cs_config-draft_exp_time_in_hours = 8. @@ -47,21 +47,4 @@ CLASS zcl_a2ui5_user_exit IMPLEMENTATION. ENDCLASS. ``` -::: tip The interface is being renamed -`z2ui5_if_exit` becomes -[`z2ui5_if_ui5_exit`](https://github.com/abap2UI5/abap2UI5/blob/main/src/02/z2ui5_if_ui5_exit.intf.abap), -following the framework's naming. Both work — abap2UI5 looks up both -interfaces, so an existing exit keeps running — and the examples here move to -the new name once it is in a release. On `main` the old interface has already -moved to the frozen `src/99` package, which is why the link above points -there; it still ships and is still called. See -[Deprecations](/resources/deprecations). -::: - -::: warning The tab title is not set here -`cs_config-title` is still on the structure — an exit that assigns it compiles -and runs — but nothing reads it any more. The generated page always carries -`abap2UI5`, and the title the user sees is set by the running -app with the `set_title` frontend event: see -[Title](/cookbook/browser_interaction/title). -::: + diff --git a/docs/advanced/renaming.md b/docs/advanced/renaming.md index 497acc54..d21de96b 100644 --- a/docs/advanced/renaming.md +++ b/docs/advanced/renaming.md @@ -52,7 +52,7 @@ alone would let them collide; the segment is what keeps them apart. | Segment | Meaning | |---|---| -| *(none)* — `z2ui5_if_app`, `z2ui5_if_client`, `z2ui5_if_exit` | **The public API.** The three interfaces carry no segment on purpose: they are the contract, and a contract does not move between layers. `z2ui5_if_types` carries none either and is the exception that proves the rule: it is retired, ships unchanged so existing apps keep compiling, and every type it held now sits on the object that uses it — see [Deprecations](/resources/deprecations) | +| *(none)* — `z2ui5_if_app`, `z2ui5_if_client` | **The public API.** Both interfaces carry no segment on purpose: they are the contract, and a contract does not move between layers. `z2ui5_if_types` carries none either and is the exception that proves the rule: it is retired, ships unchanged so existing apps keep compiling, and every type it held now sits on the object that uses it — see [Deprecations](/resources/deprecations) | | `ui5` | The framework itself — the engine and the shipped apps (`z2ui5_cl_ui5_handler`, `z2ui5_cl_ui5_srv_draft`, `z2ui5_cl_ui5_app_start`), plus the two public classes `z2ui5_cl_ui5_http_handler` and `z2ui5_cl_ui5_view_builder` | | `ui5f` | The UI5 **f**rontend, embedded as ABAP string constants and **generated** — never edit one by hand, the next build overwrites it | | `ajson`, `srt` | [ajson](/technical/tools/ajson) and [S-RTTI](/technical/tools/srtti), mirrored from their upstream projects under this namespace | diff --git a/docs/configuration/authorization.md b/docs/configuration/authorization.md index 15d77da3..0f7d698f 100644 --- a/docs/configuration/authorization.md +++ b/docs/configuration/authorization.md @@ -73,34 +73,63 @@ Alternatively, handle authorization within individual app classes. This approach ### Example: Authorization Check in an App Class In this approach, each app checks the user's permissions, like traditional ABAP apps. - + ```abap CLASS z2ui5_cl_app DEFINITION PUBLIC. PUBLIC SECTION. INTERFACES z2ui5_if_app. + DATA mv_status TYPE string. + + PROTECTED SECTION. + PRIVATE SECTION. ENDCLASS. CLASS z2ui5_cl_app IMPLEMENTATION. METHOD z2ui5_if_app~main. - " Run an authorization check before launching the app - AUTHORITY-CHECK OBJECT `Z_APP_AUTH` - ID `APP` FIELD `Z2UI5_APP_001`. - IF sy-subrc <> 0. - " Authorization failed, refuse access - RETURN. + IF client->check_on_navigated( ). + + " Run an authorization check before showing anything + AUTHORITY-CHECK OBJECT `Z_APP_AUTH` + ID `APP` FIELD `Z2UI5_APP_001`. + + IF sy-subrc <> 0. + " Refuse, and SAY so - a blank screen looks like a broken app + mv_status = `You are not authorized to use this app.`. + client->message_box_display( text = mv_status + type = `error` + title = `Not authorized` ). + ELSE. + mv_status = |Authorized as { sy-uname }|. + ENDIF. + + DATA(view) = z2ui5_cl_ui5_view_builder=>factory( + )->ele( n = `View` ns = `mvc` + )->a( n = `xmlns` v = `sap.m` + )->a( n = `xmlns:mvc` v = `sap.ui.core.mvc` + + )->ele( `Page` + )->a( n = `title` v = `Authorization` + + )->tag( `Text` + )->a( n = `text` v = client->_bind( mv_status ) ) ). + + client->view_display( view->stringify( ) ). + ENDIF. - " Continue with app processing if authorized - " (App logic goes here) ENDMETHOD. ENDCLASS. ``` +The refusal branch matters as much as the check. Returning without displaying +anything leaves the user on an empty frame with nothing to go on — indistinguishable +from an app that crashed. Say what happened, then return. + ::: warning If you don't add authorization checks at the app level, make sure users can't bypass service-level checks by navigating between apps. ::: diff --git a/docs/configuration/performance.md b/docs/configuration/performance.md index e466607f..c92950c5 100644 --- a/docs/configuration/performance.md +++ b/docs/configuration/performance.md @@ -48,18 +48,12 @@ METHOD z2ui5_if_app~main. ENDMETHOD. ``` -::: tip You may see `client->view_model_update( )` in older code -It used to be the way to ask for that push. It is a **no-op** now — the -framework does it unconditionally — and it is scheduled for removal. Delete -the call; nothing replaces it. -::: - ## Suggestions Want to tune your app further? A few tips: - Call `client->view_display` only when needed — on initialization and when the view structure changes. For a pure data change, set the attribute and return; the framework pushes the delta and UI5 re-renders only the controls that changed. -- Bind data with `client->_bind` — the framework sends only the paths the user actually edited back to ABAP (a delta), so read-only and untouched fields cost nothing on the return trip. (`_bind_edit` is an obsolete alias of `_bind`.) +- Bind data with `client->_bind` — the framework sends only the paths the user actually edited back to ABAP (a delta), so read-only and untouched fields cost nothing on the return trip. - Declare public attributes in your app class only for variables shown on the frontend. This keeps the framework from reading unused values. - Follow standard ABAP best practices, like cutting loops and choosing sorted tables, just like in any other ABAP project. diff --git a/docs/configuration/security.md b/docs/configuration/security.md index 82e1c579..8654a500 100644 --- a/docs/configuration/security.md +++ b/docs/configuration/security.md @@ -44,7 +44,7 @@ By default, abap2UI5 uses the CSP below (defined in `z2ui5_cl_ui5_user_exit`): If needed, adjust the CSP in the [user exit](/advanced/extensibility/user_exits). The exit runs after the framework fills in the defaults, so whatever you set there overrides the default policy: ```abap -METHOD z2ui5_if_exit~set_config_http_get. +METHOD z2ui5_if_ui5_exit~set_config_http_get. cs_config-content_security_policy = ``. @@ -55,7 +55,7 @@ ENDMETHOD. `'unsafe-eval'` weakens the protection CSP provides against script injection. The default keeps it only because OpenUI5 `1.71` — the oldest supported release — still executes fetched modules via `eval()` in its module loader. If you pin a modern UI5 release, no `eval()` is involved and you can remove `'unsafe-eval'` in the same exit where you set the bootstrap source. The example below is the default policy without `'unsafe-eval'`: ```abap -METHOD z2ui5_if_exit~set_config_http_get. +METHOD z2ui5_if_ui5_exit~set_config_http_get. cs_config-src = `https://ui5.sap.com/resources/sap-ui-core.js`. cs_config-theme = `sap_horizon`. @@ -113,7 +113,7 @@ They live in `cs_config-t_security_header` and are set in the same behind a proxy that already sets one of them can drop or change it: ```abap -METHOD z2ui5_if_exit~set_config_http_get. +METHOD z2ui5_if_ui5_exit~set_config_http_get. " keep everything the framework set, override one entry DELETE cs_config-t_security_header WHERE n = `Referrer-Policy`. @@ -129,7 +129,7 @@ Every state-changing request in abap2UI5 is a POST, so the framework ships its o **CSRF protection is active by default.** A fresh install rejects cross-origin POSTs without any configuration. If your endpoint must accept cross-origin POSTs (for example, behind a proxy setup where the origin legitimately differs), opt out in the [user exit](/advanced/extensibility/user_exits): ```abap -METHOD z2ui5_if_exit~set_config_http_post. +METHOD z2ui5_if_ui5_exit~set_config_http_post. " escape hatch - only disable this if your endpoint must accept cross-origin POSTs cs_config-check_csrf_active = abap_false. diff --git a/docs/configuration/setup.md b/docs/configuration/setup.md index 473f3b81..81d94a5a 100644 --- a/docs/configuration/setup.md +++ b/docs/configuration/setup.md @@ -3,19 +3,19 @@ outline: [2, 4] --- # Setup -Every UI5 application has an `index.html` that bootstraps the framework, picks a theme, loads a UI5 version and so on. With abap2UI5 you don't maintain that file by hand — the framework generates it on every page load. To change what ends up in it, implement the `z2ui5_if_exit` interface in your own ABAP class: +Every UI5 application has an `index.html` that bootstraps the framework, picks a theme, loads a UI5 version and so on. With abap2UI5 you don't maintain that file by hand — the framework generates it on every page load. To change what ends up in it, implement the `z2ui5_if_ui5_exit` interface in your own ABAP class: ```abap CLASS zcl_a2ui5_user_exit DEFINITION PUBLIC. PUBLIC SECTION. - INTERFACES z2ui5_if_exit. + INTERFACES z2ui5_if_ui5_exit. ENDCLASS. CLASS zcl_a2ui5_user_exit IMPLEMENTATION. - METHOD z2ui5_if_exit~set_config_http_get. + METHOD z2ui5_if_ui5_exit~set_config_http_get. " your configuration goes here ENDMETHOD. @@ -36,9 +36,9 @@ ENDCLASS. Security-relevant headers and the Content Security Policy meta tag are configured separately — see [Security](/configuration/security). -The tab title is **not** on this list. The generated page always carries `abap2UI5`, and the title the user sees is set by the running app with the `set_title` frontend event — see [Title](/cookbook/browser_interaction/title). The field `cs_config-title` still exists on `cs_config` so that existing exits compile, but nothing reads it. +The tab title is **not** on this list. The generated page always carries `abap2UI5`, and the title the user sees is set by the running app with the `set_title` frontend event — see [Title](/cookbook/browser_interaction/title). ## See Also - Official SAP documentation on [UI5 bootstrapping](https://sapui5.hana.ondemand.com/#/topic/91f2cebe7c8e4d289fd80a4f0c0bd2ca) and [configuration options](https://sapui5.hana.ondemand.com/#/topic/91f2d03b6f4d1014b6dd926db0e91070). -- The [User Exit](/advanced/extensibility/user_exits) page documents every hook on `z2ui5_if_exit`. +- The [User Exit](/advanced/extensibility/user_exits) page documents every hook on `z2ui5_if_ui5_exit`. diff --git a/docs/configuration/setup/bootstrap_attributes.md b/docs/configuration/setup/bootstrap_attributes.md index e3bac8cf..0835a72e 100644 --- a/docs/configuration/setup/bootstrap_attributes.md +++ b/docs/configuration/setup/bootstrap_attributes.md @@ -23,7 +23,7 @@ The UI5 bootstrap script tag in `index.html` accepts a long list of `data-sap-ui To add an attribute — or override one of the defaults — append a row to `cs_config-t_add_config`. Each row contributes one `name='value'` pair to the script tag: ```abap -METHOD z2ui5_if_exit~set_config_http_get. +METHOD z2ui5_if_ui5_exit~set_config_http_get. cs_config-t_add_config = VALUE #( ( n = `data-sap-ui-libs` v = `sap.m,sap.ui.table` ) diff --git a/docs/configuration/setup/logon_language.md b/docs/configuration/setup/logon_language.md index 0eb11667..8fb59445 100644 --- a/docs/configuration/setup/logon_language.md +++ b/docs/configuration/setup/logon_language.md @@ -31,7 +31,7 @@ Most apps don't need this — the browser locale and the SAP logon language agre You can also pin the UI5 locale via the bootstrap, instead of relying on a URL parameter: ```abap -METHOD z2ui5_if_exit~set_config_http_get. +METHOD z2ui5_if_ui5_exit~set_config_http_get. cs_config-t_add_config = VALUE #( ( n = `data-sap-ui-language` v = `en` ) ). diff --git a/docs/configuration/setup/style_css.md b/docs/configuration/setup/style_css.md index 0d77a57c..30b11efb 100644 --- a/docs/configuration/setup/style_css.md +++ b/docs/configuration/setup/style_css.md @@ -6,7 +6,7 @@ outline: [2, 4] UI5 supports app-specific CSS in addition to the theme. abap2UI5 injects whatever string you assign to `cs_config-styles_css` directly into a `