Technical Articles
My journey of building FIORI apps from BOPF to RAP – Part 2 (Authorization on standard CUD operations)
This is the next part for the blog series .If you have not checked the overview and previous part, Please refer : My Journey of building FIORI apps from BOPF to RAP – Part 1
In this blog, we will see the use cases to enable/disable the standard CUD (Create/Update/Delete) operations.
2. Authorization on standard CUD operations
- For any inactive instance of any entity, Modifications wouldn’t be allowed.
- Creation of new application is only allowed to ADMIN users and rest of the users should not be allowed to create any new application.
Approach in BOPF and RAP can be summarized as follow:
Use Cases |
Programming Model |
|
BOPF | RAP | |
#2 Authorization on standard CUD operations |
|
Authorization Master:
Feature Control:
|
Data Model:
For data model details, Please refer the blogpost My Journey of building FIORI apps from BOPF to RAP – Part 1
Pre-requisites:
- Good knowledge on CDS Modeling (Access Control in CDS), BOPF Framework.
- Basic knowledge in RAP Model ( Managed Implementation )
- Good understanding of Authorization Model in SAP (Authorization Object and Role).
We can achieve this use case to authorize standard CUD operations using Authorization Objects and profile settings as well as to use feature control in RAP. In this blog, we will understand all possible options and readers can decide the required approach. Let’s start to dig into implementation steps in BOPF and RAP.
Custom Authorization Object:
We will use a custom authorization object in both programming models. There are 2 authorization fields:
- Status : X(Active), space(Inactive)
- Activity : 01(Create), 02(Change), 03(Display), 06(Delete)
Approach 1 : BOPF
Create an authorization class for the relevant BO
To create an authorization exit class for the relevant BO, open the editor for the root node and choose the Authorization tab
Application specific authorization class in BOPF
Implement static checks in the CHECK_STATIC_AUTHORITY
This method is usually called before the execution of a BOPF core service to check whether the user has authorization to execute a specific task, such as modifying data or performing an action.
Returning parameter RV_FAILED determines if user has authorization for the action.
RV_FAILED
|
The value (true/false) indicates whether the authorization check failed
|
METHOD /bobf/if_lib_auth_draft_active~check_static_authority.
" Check the creation of new instance here
AUTHORITY-CHECK OBJECT 'ZPB_APPLICATION' FOR USER sy-uname
ID 'ACTVT' FIELD is_ctx-activity
IF sy-subrc EQ 0.
rv_failed = abap_false.
ELSE.
rv_failed = abap_true.
ENDIF.
" Message handling if authorization check failed
IF rv_failed = abap_true AND is_ctx-activity EQ /bobf/cl_frw_authority_check=>sc_activity-create.
CALL METHOD /scmtms/cl_common_helper=>msg_helper_add_symsg(
CHANGING
co_message = eo_message ).
eo_message->add_message(
is_msg = VALUE #( msgid = 'S7'
msgno = 000
msgv1 = | No authorization to create a record |
msgty = /bobf/cm_frw=>co_severity_error
)
iv_node = is_ctx-node_key
iv_key = is_ctx-bo_key
iv_attribute = zif_i_pb_application_c=>sc_node_attribute-zi_pb_application-node_data
).
ENDIF.
ENDMETHOD.
Implement instance-based checks in the CHECK_INSTANCE_AUTHORITY
This method is usually called once the static authorization check has been passed.
METHOD /bobf/if_lib_auth_draft_active~check_instance_authority.
DATA: lt_context_data TYPE ztipb_application,
ls_message_textid TYPE scx_t100key. " T100 key with parameters
" Retrieve the data of the requested node instance
io_read->retrieve(
exporting
iv_node = is_ctx-node_key
it_key = it_key
importing
et_data = lt_context_data
et_failed_key = et_failed_key
).
LOOP AT lt_context_data ASSIGNING FIELD-SYMBOLS(<ls_context>).
DATA(lv_denied) = abap_true. " Deny access by default
" Check Update/Delete of selected instance here
AUTHORITY-CHECK OBJECT 'ZPB_APPLICATION'
ID 'ACTVT' FIELD is_ctx-activity
ID 'ZPB_STATUS' FIELD <ls_context>-isActive.
IF sy-subrc EQ 0.
lv_denied = abap_false.
ENDIF.
" Message handling if authorization check failed
IF lv_denied = abap_true.
INSERT VALUE #( key = <ls_context>-key ) INTO TABLE et_failed_key.
ENDIF.
ENDLOOP.
ENDMETHOD.
Approach 2 : RAP
In RAP BOs, standard operations can be checked against any unauthorized access during runtime. There are 2 ways by which we can provide authorizations on standard operations:
- Authorization defined on Behavior definition with Authorization master
- Feature control on standard operations (Create/Update/Delete)
1. Authorization on Entity
Global Authorization : used for all authorization checks depending on user
Instance Authorization : in addition to user role, It’s used for selected instance of the entity.
Note: CREATE operation and static scope actions are not valid for Instance authorization
Behavior Definition:
Go to behavior definition and set the authorization master as global and instance both on root entity.
define behavior for ZI_PB_ACTIVE_APPL alias Application
implementation in class zcl_i_pb_active_appl unique
persistent table zpb_active_appl
lock master
authorization master ( global, instance )
etag master LocalLastChangedAt
{
create ;
update ;
delete ;
association _Company { create; }
}
Go to behavior definition for associated entity and set the authorization as dependent on root.
define behavior for ZI_PB_ACTIVE_COMP alias Company
implementation in class zcl_i_pb_active_comp unique
persistent table zpb_active_comp
lock dependent by _Application
authorization dependent by _Application
etag master LocalLastChangedAt
{
update ;
delete ;
}
Behavior Implementation:
As soon as we will activate the above behavior definition, we will see 2 methods created in behavior implementation for GLOBAL and INSTANCE authorizations respectively.
Global Authorization:
Go to method GET_GLOBAL_AUTHORIZATIONS and check if user is authorized for CUD operations.
METHOD get_global_authorizations.
" Check the creation of new instance here
AUTHORITY-CHECK OBJECT 'ZPB_APPLICATION' FOR USER sy-uname
ID 'ACTVT' FIELD '01'.
IF sy-subrc = 0.
DATA(lv_authorized) = abap_true.
ENDIF.
result = VALUE #( %create = COND #( WHEN lv_authorized IS INITIAL THEN if_abap_behv=>fc-o-disabled ELSE if_abap_behv=>fc-o-enabled ) ).
CHECK lv_authorized IS INITIAL.
APPEND VALUE #( %state_area = 'AUTH_CREATE'
%msg = NEW zcx_pb_application( iv_severity = if_abap_behv_message=>severity-error
is_textid = zcx_pb_application=>tys_create_not_allowed
iv_userid = CONV #( cl_abap_context_info=>get_user_technical_name( ) )
iv_context = 'Application' )
) TO reported-application.
ENDMETHOD.
Instance Authorization:
Go to method GET_INSTANCE_AUTHORIZATIONS and check if user is authorized to delete/update and create the associated entity instances for Inactive status of selected instance.
METHOD get_instance_authorizations.
** Read the status of current application record
READ ENTITIES OF zi_pb_active_appl IN LOCAL MODE
ENTITY Application
FIELDS ( IsActive ) WITH CORRESPONDING #( keys )
RESULT DATA(lt_context_data)
FAILED failed.
result = VALUE #( FOR ls_data IN lt_context_data
LET lv_authorization = COND #( WHEN _IsAuthorized( ls_data-IsActive ) IS INITIAL THEN if_abap_behv=>auth-unauthorized ELSE if_abap_behv=>auth-allowed )
IN ( %tky = ls_data-%tky
%assoc-_Company = lv_authorization
%delete = lv_authorization
%update = lv_authorization )
).
ENDMETHOD.
METHOD _IsAuthorized.
" Check Create of selected instance here
AUTHORITY-CHECK OBJECT 'ZPB_APPLICATION'
ID 'ACTVT' FIELD '01'
ID 'ZPB_STATUS' FIELD iv_status.
IF sy-subrc EQ 0.
rv_authorized = abap_true.
ENDIF.
ENDMETHOD.
2. Feature Control on Standard Operations
In the previous blog My Journey of building FIORI apps from BOPF to RAP – Part 1
We’ve seen that feature control can be used on custom actions to define the visibility. Similarly, we can also use feature control on CUD operations by selecting the scope( Global/Instance ).
Note: Its just another way to control the behavior of standard operations. If you are going with authorization control on entity, please try to avoid this.
Behavior Definition:
Go to behavior definition and set the feature control on CREATE as global and DELETE/UPDATE as instance on root entity.
define behavior for ZI_PB_ACTIVE_APPL alias Application
implementation in class zcl_i_pb_active_appl unique
persistent table zpb_active_appl
lock master
authorization master ( instance )
etag master LocalLastChangedAt
{
create ( features : global );
update ( features : instance );
delete ( features : instance );
association _Company { create ( features : instance ); }
}
Go to behavior definition for associated entity and set the feature control on DELETE/UPDATE as instance.
define behavior for ZI_PB_ACTIVE_COMP alias Company
implementation in class zcl_i_pb_active_comp unique
persistent table zpb_active_comp
lock dependent by _Application
authorization dependent by _Application
etag master LocalLastChangedAt
{
update ( features : instance );
delete ( features : instance );
association _Language { create ( features : instance ); }
association _Application { }
}
Behavior Implementation:
As soon as we will activate the above behavior definition, we will see 2 methods created in behavior implementation for GLOBAL and INSTANCE feature controls respectively.
Global Feature Control:
Go to method GET_GLOBAL_FEATURES and check if user is authorized for CUD operations.
METHOD get_global_features.
" Check the creation of new instance here
AUTHORITY-CHECK OBJECT 'ZPB_APPLICATION' FOR USER sy-uname
ID 'ACTVT' FIELD '01'.
IF sy-subrc = 0.
DATA(lv_authorized) = abap_true.
ENDIF.
result = VALUE #( %create = COND #( WHEN lv_authorized IS INITIAL THEN if_abap_behv=>fc-o-disabled ELSE if_abap_behv=>fc-o-enabled ) ).
APPEND VALUE #( %state_area = 'AUTH_CREATE'
%msg = NEW zcx_pb_application( iv_severity = if_abap_behv_message=>severity-error
is_textid = zcx_pb_application=>tys_create_not_allowed
iv_userid = CONV #( cl_abap_context_info=>get_user_technical_name( ) )
iv_context = 'Application' )
) TO reported-application.
ENDMETHOD.
Instance Feature Control:
Go to method GET_INSTANCE_FEATURES and check if user is authorized to delete/update and create the associated entity instances for Inactive status of selected instance.
METHOD get_instance_features.
** Read the status of current application record
READ ENTITIES OF zi_pb_active_appl IN LOCAL MODE
ENTITY Application
FIELDS ( IsActive ) WITH CORRESPONDING #( keys )
RESULT DATA(lt_context_data)
FAILED failed.
result = VALUE #( FOR ls_data IN lt_context_data
LET lv_active = COND #( WHEN _IsAuthorized( ls_data-IsActive ) IS INITIAL THEN if_abap_behv=>fc-o-disabled ELSE if_abap_behv=>fc-o-enabled )
IN ( %tky = ls_data-%tky
%assoc-_Company = lv_active
%delete = lv_active
%update = lv_active )
).
ENDMETHOD.
METHOD _IsAuthorized.
" Check Create of selected instance here
AUTHORITY-CHECK OBJECT 'ZPB_APPLICATION'
ID 'ACTVT' FIELD '01'
ID 'ZPB_STATUS' FIELD iv_status.
IF sy-subrc EQ 0.
rv_authorized = abap_true.
ENDIF.
ENDMETHOD.
App Preview:
For an Inactive application ( APPL2 ), Edit and Delete operations for that instance are not allowed. On List Page, Delete button will be disabled and on Object page, Edit and Delete buttons will not be available. Also, Create button for child entity ( Company ) will not be available.
FIORI app behavior for Inactive Application
However, for an active application ( APPL1 ), Delete operation is available on List page and object page and Edit is also available on Object page. Also, Create for child entity is also available.
FIORI app preview for Active application
Conclusion:
In this blog, various options to control the unauthorized access on standard CUD operations have been discussed via BOPF and RAP models. We can also restrict the unauthorized data to be displayed on FIORI app using DCL (Data Control Language) CDS views.
In next blog in this series, we will cover the use cases to display a popup dialog using BOPF and RAP ( of course without any UI5 development ). SO stay tuned and share your feedback in comment section regarding authorization concept.
Hi Prabhjot,
Great blog.nice explanation with step by step.
Looking for more blogs on RAP.
Thank you,
Syam
Thanks and stay tuned for more practical scenarios in upcoming weeks. You can get an overview of the topics in first part My journey of building FIORI apps from BOPF to RAP – Part 1
Thank you very much for the post, a good way to start the change to RAP 🙂
Thanks, Good blog series, Shall try soon.
Best Regards,
Pavan Golesar