Authorization control in ABAP Queries is a grey area. One may want to restrict data access at table level, record level, selection level etc.
This Blog tries to explain the concept of record level authorization check with an example of HR LDB based query.
As you may know, an Infoset may contain one or more tables. In HR, we use PNP LDB to create infoset. Such an infoset contains multiple infotypes as data sources. Then we create queries by selecting fields from infotypes of our choice.
Now if we want to check whether the user has read authorization on the infotypes selected, we need to know at design/coding time that which infotypes to check for authorization? This is a difficult task to know in advance what infotypes user may use in his/her queries.
We will see how we will adapt our Infoset in SQ02 to be able to make a dynamic authorization check based on the roles assigned to user. The example is a simple query to display the employee salary data.
- At start of selection, dynamically determine infotypes accessed.
- At every record, check if user has read authorization on infotypes selected in step 1 using this record’s data.
- Remove unauthorised data.
Declare global data
Go to SQ02 and select your infoset.
Then go to extras
click on the Code tab and select “Data” in code selection drop down.
Here we will define our global internal table to hold names of infotypes used in current query
data: it_name type tabnam, it_list like table of it_name.
Determine Infotypes used in current Query
The best place in code to do this step is “Start of Selection” event because Its a one time code and should be run before any record is processed. Therefore, select “Start-of-Selection” in Code selection drop down
ABAP queries always define an internal table %G00 which holds the final data. However, its type is generic and is only determined at runtime. Each column in %G00 has name of the form <table_name>-<column_name>. We also know that each infotype name always start with letter “P”.
Using this information, we will loop through %G00 columns at runtime, and extract table names from these column names. Then we will verify that table is actually an infotype. Once sure that its an infotype, we will add this to our list of tables to be checked for authorizations. Following is the code
DATA: ls_comp TYPE abap_componentdescr, ls_stru TYPE REF TO cl_abap_structdescr, lt_comp TYPE STANDARD TABLE OF abap_componentdescr WITH KEY name, vinfty type infty. field-symbols: <fs_wa>. assign ('%G00') to <fs_wa>. *get dynamic if ls_stru is INITIAL . ls_stru ?= cl_abap_typedescr=>describe_by_data( <fs_wa> ). lt_comp = ls_stru->get_components( ). unassign <fs_wa>. LOOP AT lt_comp INTO ls_comp . clear: it_name. * read table name from field name split ls_comp-name at '-' into it_name ls_comp-name. * check if already checked read table it_list from it_name into it_name. if sy-subrc ne 0. vinfty = it_name+1. "skip first p * make sure its infotype select single infty into vinfty from T582A where infty = vinfty. * yes, its infotype, append it if sy-subrc = 0. append it_name to it_list. endif. endif. endloop. sort it_list. delete ADJACENT DUPLICATES FROM it_list. endif.
Implement Authorization check
Now comes the second tricky part to determine the location for implementing the check.
As a general rule, if the authorization check is only at table level, it can be implemented in “Start-of-Selection” section. Otherwise, If check is to be executed for every record selected, then it should be implemented in “Record Processing” block. Latter is the case we will be using.
Once location determined, finalize the authorization object to be used in authority check and its fields to be used. Make sure you have the data to be supplied to the fields. We will use standard authorization object “P_ORGIN” with INFTY field supplied from our internal table of infotypes and PERSA field supplied from the record data.
DATA: wa0001 TYPE p0001. data: lv_itname(7) type c . field-symbols: <it> type any table. READ TABLE p0001 INTO wa0001 index 1. *check auth for each pernr loop at it_list into it_name. *test if this infotype is fetched in this query concatenate it_name '' into lv_itname. assign (lv_itname) to <it>. if <it> is assigned. if <it> is not initial. * check auth AUTHORITY-CHECK OBJECT 'P_ORGIN' ID 'INFTY' FIELD it_name+1 ID 'AUTHC' FIELD 'R' ID 'PERSA' FIELD wa0001-werks. if sy-subrc ne 0. clear <it>. message 'Unauthorized data removed.' type 'S'. endif. endif. unassign <it>. endif. endloop.
Here we go. Once this is done all queries build up on this infoset will restrict the result based on the authorization of the user.