[ZFS] Encryption

Native encryption in ZFS is supported since version 0.8.0. Check your current ZFS version with:

modinfo zfs                           

First activate the encryption feature on your pool:

zpool set feature@encryption=enabled pool_name

To get an overview of all pools with enabled encryption use the following command:

zpool get all | grep encryption

To create a new encrypted dataset with a passphrase:

zfs create -o encryption=aes-256-gcm -o keyformat=passphrase pool_name/dataset_name

Check the keystatus, the current encryption type and the mountpoint with the following commands:

zfs get keystatus pool_name/dataset_name
zfs get encryption pool_name/dataset_name
zfs list pool_name/dataset_name

Change the passphrase with:

zfs change-key pool_name/dataset_name

After a reboot you first have to load your key and then mount your dataset:

zfs load-key pool_name/dataset_name
zfs mount pool_name/dataset_name

Unmount and unload your key:

zfs umount pool_name/dataset_name
zfs unload-key pool_name/dataset_name

If you are sharing this dataset via NFS, it could be necessary to restart the NFS service after mounting. I just deactivate and activate again NFS on the dataset.

zfs set sharenfs=off pool_name/dataset_name
zfs set sharenfs=on pool_name/dataset_name

[Fiori] Send notification mail if workitem is forwarded in MyInbox

Workitem function modules

If you forward a workitem manually from the MyInbox or via function module SAP_WAPI_FORWARD_WORKITEM, the function module SWW_WI_FORWARD will be called. There the SAP implemented a BAdI call of the BAdI WF_WI_FORWARD.

BAdI WF_WI_FORWARD

The BAdI provides a method to add additional checks, when forwarding a workitem. I will use it, to send notification mails.

BAdI Filter

Create your own BAdI implementation and add a task id as filter. In my case it’s the task TS21500003 of the leave request approval workflow.
Now your implementation will only be called, if this specific workitem is forwarded. Now we implement the method CHECK_BEFORE_FORWARD. The method has enough parameters to get all necessary information to enrich the mail text.

IF_EX_WF_WI_WORKITEM~CHECK_BEFORE_FORWARD Paramter

First the workitem container is read out of the context. There we get _WI_OBJECT_ID element, which contains the request object reference. With this information we are able to get the current request object out of the workflow. I pass this into antother class where i already have a mail sending implementation.

  METHOD if_ex_wf_wi_workitem~check_before_forward.
*---------------------------------------------------------------------------------*
* This BAdI implementation is used to send a info mail when a workitem is forwarded.
*---------------------------------------------------------------------------------*

    TRY.

        "Get workitem container and requestId
        DATA(container) = im_workitem_context->get_wi_container( ).

        container->get_value_ref( EXPORTING name       = |_WI_OBJECT_ID|
                                  IMPORTING value_ref  = DATA(lr_req_id) ).

        ASSIGN lr_req_id->* TO FIELD-SYMBOL(<lpor>).

        "Get current request object
        DATA(lo_req) = NEW cl_pt_req_wf_attribs( )->bi_persistent~find_by_lpor( lpor = <lpor> ).

        "Send an info mail to each new agent (should be only one)
        LOOP AT im_table_new_agents INTO DATA(new_agent).
          zcl_hcm_leave_request_assist=>send_mail( io_req         = CAST cl_pt_req_wf_attribs( lo_req )
                                                   iv_tdname      = mc_mailtext
                                                   iv_pernr       = cl_hcmfab_employee_api=>get_instance( )->get_employeenumber_from_user( iv_user = new_agent-objid ) ).
        ENDLOOP.


      CATCH cx_hcmfab_common.
      CATCH cx_swf_cnt_elem_not_found.
      CATCH cx_swf_cnt_container.
        "In error case, do nothing. The workitem should still be forwarded.
        RETURN.
    ENDTRY.

    "Write Info to WF Log
    MESSAGE s001(00) WITH |Forward: Mail { mc_mailtext }| INTO DATA(lv_message).
    im_workitem_context->set_message_to_log( im_function = CONV #( lv_message )         "max char30
                                             im_message = VALUE #( msgid = sy-msgid
                                                                   msgty = sy-msgty
                                                                   msgno = sy-msgno
                                                                   msgv1 = sy-msgv1 ) ).
    COMMIT WORK.
  ENDMETHOD.

At the end I’m writing a little notification in the workflow log. The workitem context provides the method set_message_to_log for this. The log will look like this.

[ABAP] Access leave request attributes

cl_pt_req_badi=>get_request( EXPORTING im_req_id  = request_id
                             IMPORTING ex_request = DATA(request) ).

request->get_all_attribs( IMPORTING ex_attribs_struc = DATA(req_attribs) ).

DATA(req_begda) = req_attribs-version-item_tab[ 10 ]-value.

Take a look in the item_tab to see the specific request values.

[Workflow] Add custom message in workflow log

In a function exit of a workflow task, you can copy the sample coding out of class CL_SWH_WORKITEM_EXIT_LOG to append a custom message

METHOD if_swf_ifs_workitem_exit~event_raised .
  DATA: ls_msg TYPE swr_mstruc.
  DATA: ls_por TYPE sibflporb.
  DATA: l_cnt TYPE REF TO if_swf_ifs_parameter_container.

  me->m_ctx = im_workitem_context.
  IF im_event_name EQ swrco_event_after_creation.
    ls_msg-msgid = 'SWH'.
    ls_msg-msgty = 'S'.
    ls_msg-msgno = '100'.
    ls_msg-msgv1 = 'CL_SWH_WORKITM_EXIT_LOG'.
    ls_msg-msgv2 = 'swrco_event_after_creation'.
    l_cnt = m_ctx->get_wi_container( ).
    TRY.
        CALL METHOD l_cnt->get
          EXPORTING
            name  = swrco_wi_leading_object
          IMPORTING
            value = ls_por.
        CALL METHOD m_ctx->set_message_to_log
          EXPORTING
            im_message    = ls_msg
            im_object_por = ls_por.
      CATCH cx_swf_cnt_container .
    ENDTRY.
  ENDIF.
ENDMETHOD.                    "IF_SWF_IFS_WORKITEM_EXIT~EVENT_RAISED

But to add a message in general, only the workitem context is needed. If you got the context, just use method set_message_to_log.

* context type: im_workitem_context TYPE REF TO if_wapi_workitem_context   

" text in im_function will be displayed in workitem log (max char30),
" message in im_message will give further information when clicking on the traffic light (max char 70).
im_workitem_context->set_message_to_log( im_function = |Forward: Mail { var }|
                                         im_message = VALUE #( msgid = '00'
                                                               msgty = 'S'
                                                               msgno = '000'
                                                               msgv1 = |var 1|
                                                               msgv2 = |var 2| ) ).
* In some cases "COMMIT WORK" is needed.

You’ll find the log entry in workitem flog view:

[ABAP] User <-> Employeenumber

Class:
CL_HCMFAB_EMPLOYEE_API
Methods:
GET_USERID_FROM_EMPLOYEENUMBER
GET_EMPLOYEENUMBER_FROM_USER

How to use the class:

TRY.
    DATA(lv_pernr) = cl_hcmfab_employee_api=>get_instance( )->get_employeenumber_from_user( sy-uname ) )
  CATCH cx_hcmfab_common.
ENDTRY.

[NGINX] Reverse Proxy

As I installed OnlyOffice to edit Word and Excel files directly from my Nextcloud, I had to setup a reverse proxy because OnlyOffice needs to run on a separate Server/Container and has to be reachable via https. First I tried to setup Nginx manually (way to complicated to handle in my opinion), then I tried Traefik (if you’re running a docker einvironment, I’m sure that’s a good solution) and in the end, I stuck with Nginx Proxy Manager. If you already have docker installed, this is by far the easiest way and also provides an awesome WebUI, where you can manage all your proxy hosts and SSL certificates.

The installation is done in just three simple steps: Set the port fowarding (80 and 443) in your router to your server/container, grab all the files in the doc/example/ folder and run

docker-compose up -d

And it’s done.
Now just enter the WebUI (ip:81) and setup all your routes.

[Fiori] Leave Request Approval Steps with Custom Workflow

If you want to copy the standard workflow of the leave request approval process (WS12300111) and are adding antoher approval step (or you just want to add an esacalation where you set the approve workitem to obsolete and create a new approval step for the next approver) you have to implement the following BAdI. In detail you only have to add the new step ID in the filter, else the approver will not see any approval or reject buttons in his inbox. See details here.

BAdI: /IWWRK/BADI_WF_BEFORE_UPD_IB

Defaul implementation: HCMFAB_LEAVE_APPROVAL_INBOX
Default Workflows and Step ID’s
Add your custom workflow and the custom approval step id in your own BAdI implementation

As second step you have to add the Worklow in the customizing. You’ll find further information here.

SM30 View /IWWRK/V_WFSTEP.
Add the Workflow with Approval StepId
Add the Approve and Reject Buttons