From 0d35e9377e044888bcbde78d2c435adcb3dea0e3 Mon Sep 17 00:00:00 2001 From: Marc Bernard <59966492+mbtools@users.noreply.github.com> Date: Fri, 23 Feb 2024 14:09:38 +0100 Subject: [PATCH] HTTP connection check and improved error messages (#6806) Co-authored-by: abaplint[bot] <24845621+abaplint[bot]@users.noreply.github.com> Co-authored-by: Lars Hvam --- src/http/zcl_abapgit_http.clas.abap | 213 ++++++++++++++---- .../lib/zcl_abapgit_gui_chunk_lib.clas.abap | 4 +- .../zcl_abapgit_gui_page_addonline.clas.abap | 2 + .../zcl_abapgit_gui_page_repo_view.clas.abap | 47 +++- .../zcl_abapgit_gui_page_sett_remo.clas.abap | 5 + ...t_gui_page_sett_remo.clas.testclasses.abap | 4 +- .../routing/zcl_abapgit_gui_router.clas.abap | 33 +++ src/ui/zabapgit_css_common.w3mi.data.css | 3 +- src/zif_abapgit_definitions.intf.abap | 1 + 9 files changed, 258 insertions(+), 54 deletions(-) diff --git a/src/http/zcl_abapgit_http.clas.abap b/src/http/zcl_abapgit_http.clas.abap index 2aa7cf83b..9eaaacee0 100644 --- a/src/http/zcl_abapgit_http.clas.abap +++ b/src/http/zcl_abapgit_http.clas.abap @@ -28,6 +28,12 @@ CLASS zcl_abapgit_http DEFINITION VALUE(ro_client) TYPE REF TO zcl_abapgit_http_client RAISING zcx_abapgit_exception . + + CLASS-METHODS check_connection + IMPORTING + !iv_url TYPE string + RAISING + zcx_abapgit_exception. PROTECTED SECTION. CLASS-METHODS check_auth_requested @@ -51,6 +57,24 @@ CLASS zcl_abapgit_http DEFINITION VALUE(rv_scheme) TYPE string RAISING zcx_abapgit_exception . + + CLASS-METHODS get_http_client + IMPORTING + !iv_url TYPE string + RETURNING + VALUE(ri_client) TYPE REF TO if_http_client + RAISING + zcx_abapgit_exception. + + CLASS-METHODS get_connection_longtext + IMPORTING + !iv_host TYPE string + !iv_ssl_id TYPE ssfapplssl + !iv_proxy_host TYPE string + !iv_proxy_service TYPE string + RETURNING + VALUE(rv_longtext) TYPE string. + PRIVATE SECTION. ENDCLASS. @@ -123,55 +147,22 @@ CLASS zcl_abapgit_http IMPLEMENTATION. ENDMETHOD. + METHOD check_connection. + " Check if a connection from this system to the git host is possible + " This will validate the general HTTP/HTTPS/SSL configuration and certificates + get_http_client( iv_url ). + ENDMETHOD. + + METHOD create_by_url. - DATA: lv_uri TYPE string, - lv_scheme TYPE string, - lv_authorization TYPE string, - li_client TYPE REF TO if_http_client, - ls_header LIKE LINE OF it_headers, - lo_proxy_configuration TYPE REF TO zcl_abapgit_proxy_config, - lv_text TYPE string. + DATA: lv_uri TYPE string, + lv_scheme TYPE string, + lv_authorization TYPE string, + li_client TYPE REF TO if_http_client, + ls_header LIKE LINE OF it_headers. - - CREATE OBJECT lo_proxy_configuration. - - li_client = zcl_abapgit_exit=>get_instance( )->create_http_client( iv_url ). - - IF li_client IS NOT BOUND. - - cl_http_client=>create_by_url( - EXPORTING - url = zcl_abapgit_url=>host( iv_url ) - ssl_id = zcl_abapgit_exit=>get_instance( )->get_ssl_id( ) - proxy_host = lo_proxy_configuration->get_proxy_url( iv_url ) - proxy_service = lo_proxy_configuration->get_proxy_port( iv_url ) - IMPORTING - client = li_client - EXCEPTIONS - argument_not_found = 1 - plugin_not_active = 2 - internal_error = 3 - OTHERS = 4 ). - IF sy-subrc <> 0. - CASE sy-subrc. - WHEN 1. - " make sure: - " a) SSL is setup properly in STRUST - lv_text = 'HTTPS ARGUMENT_NOT_FOUND | STRUST/SSL Setup correct?'. - WHEN OTHERS. - " Make sure ANONYM PSE exists in transaction STRUST, https://github.com/abapGit/abapGit/issues/6768 - lv_text = 'While creating HTTP Client'. - - ENDCASE. - zcx_abapgit_exception=>raise( lv_text ). - ENDIF. - - ENDIF. - - IF lo_proxy_configuration->get_proxy_authentication( iv_url ) = abap_true. - zcl_abapgit_proxy_auth=>run( li_client ). - ENDIF. + li_client = get_http_client( iv_url ). CREATE OBJECT ro_client EXPORTING @@ -244,6 +235,136 @@ CLASS zcl_abapgit_http IMPLEMENTATION. ENDMETHOD. + METHOD get_connection_longtext. + + CONSTANTS lc_docs TYPE string VALUE 'https://docs.abapgit.org/user-guide/setup/ssl-setup.html'. + + DATA lv_proxy TYPE string. + + IF iv_proxy_host IS NOT INITIAL. + lv_proxy = | via proxy { iv_proxy_host }:{ iv_proxy_service }|. + ENDIF. + + rv_longtext = |abapGit is trying to connect to { iv_host } | + && |using SSL certificates under { iv_ssl_id }{ lv_proxy }. | + && |Check system parameters (transaction | + && zcl_abapgit_html=>create( )->a( + iv_txt = 'RZ10' + iv_act = |{ zif_abapgit_definitions=>c_action-jump_transaction }?transaction=RZ10| + iv_class = 'no-pad' ) + && |), SSL setup (transaction | + && zcl_abapgit_html=>create( )->a( + iv_txt = 'STRUST' + iv_act = |{ zif_abapgit_definitions=>c_action-jump_transaction }?transaction=STRUST| + iv_class = 'no-pad' ) + && |), Internet connection monitor (transaction | + && zcl_abapgit_html=>create( )->a( + iv_txt = 'SMICM' + iv_act = |{ zif_abapgit_definitions=>c_action-jump_transaction }?transaction=SMICM| + iv_class = 'no-pad' ) + && |)|. + + IF lv_proxy IS NOT INITIAL. + rv_longtext = rv_longtext + && |, and proxy configuration (| + && zcl_abapgit_html=>create( )->a( + iv_txt = 'global settings' + iv_act = |{ zif_abapgit_definitions=>c_action-go_settings }| + iv_class = 'no-pad' ) + && |)|. + ENDIF. + + rv_longtext = rv_longtext + && |. It's recommended to get your SAP Basis and network teams involved. | + && |For more information and troubleshooting, see the | + && zcl_abapgit_html=>create( )->a( + iv_txt = 'abapGit documentation' + iv_act = |{ zif_abapgit_definitions=>c_action-url }?url={ lc_docs }| + iv_class = 'no-pad' ) + && |.|. + + ENDMETHOD. + + + METHOD get_http_client. + + DATA: + lv_error TYPE string, + lv_longtext TYPE string, + lv_host TYPE string, + lv_ssl_id TYPE ssfapplssl, + lv_proxy_host TYPE string, + lv_proxy_service TYPE string, + lo_proxy_configuration TYPE REF TO zcl_abapgit_proxy_config. + + CREATE OBJECT lo_proxy_configuration. + + ri_client = zcl_abapgit_exit=>get_instance( )->create_http_client( iv_url ). + + IF ri_client IS INITIAL. + + lv_host = zcl_abapgit_url=>host( iv_url ). + lv_ssl_id = zcl_abapgit_exit=>get_instance( )->get_ssl_id( ). + lv_proxy_host = lo_proxy_configuration->get_proxy_url( iv_url ). + lv_proxy_service = lo_proxy_configuration->get_proxy_port( iv_url ). + + lv_longtext = get_connection_longtext( + iv_host = lv_host + iv_ssl_id = lv_ssl_id + iv_proxy_host = lv_proxy_host + iv_proxy_service = lv_proxy_service ). + + cl_http_client=>create_by_url( + EXPORTING + url = lv_host + ssl_id = lv_ssl_id + proxy_host = lv_proxy_host + proxy_service = lv_proxy_service + IMPORTING + client = ri_client + EXCEPTIONS + argument_not_found = 1 + plugin_not_active = 2 + internal_error = 3 + pse_not_found = 4 + pse_not_distrib = 5 + pse_errors = 6 + OTHERS = 7 ). + IF sy-subrc <> 0. + CASE sy-subrc. + WHEN 1. + lv_error = 'ARGUMENT_NOT_FOUND'. + WHEN 2. + lv_error = 'PLUGIN_NOT_ACTIVE'. + WHEN 3. + lv_error = 'INTERNAL_ERROR'. + WHEN 4. + lv_error = 'PSE_NOT_FOUND'. + WHEN 5. + lv_error = 'PSE_NOT_DISTRIB'. + WHEN 6. + lv_error = 'PSE_ERRORS'. + WHEN OTHERS. + lv_error = |OTHER_ERROR_{ sy-subrc }|. + ENDCASE. + IF sy-subrc BETWEEN 4 AND 6. + zcx_abapgit_exception=>raise_t100( iv_longtext = lv_longtext ). + ELSE. + zcx_abapgit_exception=>raise( + iv_text = |Error { lv_error } creating HTTP connection. Check the configuration| + iv_longtext = lv_longtext ). + ENDIF. + ENDIF. + + ENDIF. + + IF lo_proxy_configuration->get_proxy_authentication( iv_url ) = abap_true. + zcl_abapgit_proxy_auth=>run( ri_client ). + ENDIF. + + ENDMETHOD. + + METHOD is_local_system. DATA: lv_host TYPE string, diff --git a/src/ui/lib/zcl_abapgit_gui_chunk_lib.clas.abap b/src/ui/lib/zcl_abapgit_gui_chunk_lib.clas.abap index f50f7448a..0b00c948a 100644 --- a/src/ui/lib/zcl_abapgit_gui_chunk_lib.clas.abap +++ b/src/ui/lib/zcl_abapgit_gui_chunk_lib.clas.abap @@ -467,6 +467,8 @@ CLASS zcl_abapgit_gui_chunk_lib IMPLEMENTATION. lv_longtext = |{ lv_longtext }

{ }

{ cl_abap_char_utilities=>newline }|. ENDLOOP. + + lv_longtext = |{ lv_longtext }
|. ENDIF. ri_html->add( |
| ). @@ -490,7 +492,7 @@ CLASS zcl_abapgit_gui_chunk_lib IMPLEMENTATION. iv_msgno = ix_error->if_t100_message~t100key-msgno ). IF lv_title IS NOT INITIAL. - lv_text = |Message ({ ix_error->if_t100_message~t100key-msgid }/{ ix_error->if_t100_message~t100key-msgno })|. + lv_text = |Message E{ ix_error->if_t100_message~t100key-msgno }({ ix_error->if_t100_message~t100key-msgid })|. ri_html->add_a( iv_txt = lv_text diff --git a/src/ui/pages/zcl_abapgit_gui_page_addonline.clas.abap b/src/ui/pages/zcl_abapgit_gui_page_addonline.clas.abap index 91a2e44bb..159294328 100644 --- a/src/ui/pages/zcl_abapgit_gui_page_addonline.clas.abap +++ b/src/ui/pages/zcl_abapgit_gui_page_addonline.clas.abap @@ -229,6 +229,8 @@ CLASS zcl_abapgit_gui_page_addonline IMPLEMENTATION. iv_key = c_id-url iv_val = lx_err->get_text( ) ). ENDTRY. + + zcl_abapgit_http=>check_connection( lv_url ). ENDIF. IF io_form_data->get( c_id-package ) IS NOT INITIAL. diff --git a/src/ui/pages/zcl_abapgit_gui_page_repo_view.clas.abap b/src/ui/pages/zcl_abapgit_gui_page_repo_view.clas.abap index e98dc3f1e..78792c67d 100644 --- a/src/ui/pages/zcl_abapgit_gui_page_repo_view.clas.abap +++ b/src/ui/pages/zcl_abapgit_gui_page_repo_view.clas.abap @@ -43,6 +43,7 @@ CLASS zcl_abapgit_gui_page_repo_view DEFINITION DATA mo_repo TYPE REF TO zcl_abapgit_repo . DATA mo_repo_aggregated_state TYPE REF TO zcl_abapgit_repo_item_state. + DATA mv_connection_error TYPE abap_bool. DATA mv_cur_dir TYPE string . DATA mv_hide_files TYPE abap_bool . DATA mv_max_lines TYPE i . @@ -192,6 +193,10 @@ CLASS zcl_abapgit_gui_page_repo_view DEFINITION RAISING zcx_abapgit_exception. + METHODS check_connection + RAISING + zcx_abapgit_exception. + ENDCLASS. @@ -576,6 +581,22 @@ CLASS zcl_abapgit_gui_page_repo_view IMPLEMENTATION. ENDMETHOD. + METHOD check_connection. + + DATA lo_repo TYPE REF TO zif_abapgit_repo_online. + + mv_connection_error = abap_true. + + IF mo_repo->is_offline( ) = abap_false. + lo_repo ?= mo_repo. + zcl_abapgit_http=>check_connection( lo_repo->get_url( ) ). + ENDIF. + + mv_connection_error = abap_false. + + ENDMETHOD. + + METHOD constructor. DATA: lo_settings TYPE REF TO zcl_abapgit_settings, @@ -1229,6 +1250,26 @@ CLASS zcl_abapgit_gui_page_repo_view IMPLEMENTATION. " Reinit, for the case of type change mo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( mo_repo->get_key( ) ). + IF mv_connection_error = abap_true. + " If connection doesn't work, render a minimal header + ri_html->add( |
| ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( + io_repo = mo_repo + iv_show_edit = abap_true + iv_show_branch = abap_false + iv_show_commit = abap_false + iv_interactive_branch = abap_false ) ). + ri_html->add( '
' ). + + ri_html->add( render_head_line( ) ). + + " Reset error flag to try connecting again next time + CLEAR mv_connection_error. + RETURN. + ENDIF. + + check_connection( ). + check_branch( ). mv_are_changes_recorded_in_tr = zcl_abapgit_factory=>get_sap_package( mo_repo->get_package( ) @@ -1346,11 +1387,7 @@ CLASS zcl_abapgit_gui_page_repo_view IMPLEMENTATION. " and allow troubleshooting of issue zcl_abapgit_persistence_user=>get_instance( )->set_repo_show( || ). - ri_html->add( render_head_line( ) ). - - ri_html->add( zcl_abapgit_gui_chunk_lib=>render_error( - iv_extra_style = 'repo_banner' - ix_error = lx_error ) ). + RAISE EXCEPTION lx_error. ENDTRY. register_deferred_script( render_scripts( ) ). diff --git a/src/ui/pages/zcl_abapgit_gui_page_sett_remo.clas.abap b/src/ui/pages/zcl_abapgit_gui_page_sett_remo.clas.abap index 57f70ae6d..9fa85cdbd 100644 --- a/src/ui/pages/zcl_abapgit_gui_page_sett_remo.clas.abap +++ b/src/ui/pages/zcl_abapgit_gui_page_sett_remo.clas.abap @@ -121,6 +121,7 @@ CLASS zcl_abapgit_gui_page_sett_remo DEFINITION METHODS validate_form IMPORTING io_form_data TYPE REF TO zcl_abapgit_string_map + iv_connection_check TYPE abap_bool DEFAULT abap_true RETURNING VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map RAISING @@ -864,6 +865,10 @@ CLASS zcl_abapgit_gui_page_sett_remo IMPLEMENTATION. iv_key = c_id-url iv_val = lx_error->get_text( ) ). ENDTRY. + + IF iv_connection_check = abap_true. + zcl_abapgit_http=>check_connection( lv_url ). + ENDIF. ENDIF. IF lv_offline = abap_false. diff --git a/src/ui/pages/zcl_abapgit_gui_page_sett_remo.clas.testclasses.abap b/src/ui/pages/zcl_abapgit_gui_page_sett_remo.clas.testclasses.abap index ff9452805..a37e95b63 100644 --- a/src/ui/pages/zcl_abapgit_gui_page_sett_remo.clas.testclasses.abap +++ b/src/ui/pages/zcl_abapgit_gui_page_sett_remo.clas.testclasses.abap @@ -378,7 +378,9 @@ CLASS ltcl_validate_form IMPLEMENTATION. METHOD when_validate_form. - mo_act_validation_log = mo_cut->validate_form( mo_given_form_data ). + mo_act_validation_log = mo_cut->validate_form( + io_form_data = mo_given_form_data + iv_connection_check = abap_false ). ENDMETHOD. diff --git a/src/ui/routing/zcl_abapgit_gui_router.clas.abap b/src/ui/routing/zcl_abapgit_gui_router.clas.abap index 02808bf2c..83bf55134 100644 --- a/src/ui/routing/zcl_abapgit_gui_router.clas.abap +++ b/src/ui/routing/zcl_abapgit_gui_router.clas.abap @@ -120,6 +120,11 @@ CLASS zcl_abapgit_gui_router DEFINITION !iv_url TYPE csequence RAISING zcx_abapgit_exception . + METHODS call_transaction + IMPORTING + !iv_tcode TYPE csequence + RAISING + zcx_abapgit_exception . METHODS get_state_settings IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event @@ -157,6 +162,30 @@ CLASS zcl_abapgit_gui_router IMPLEMENTATION. ENDMETHOD. + METHOD call_transaction. + + DATA lv_msg TYPE c LENGTH 200. + + CALL FUNCTION 'ABAP4_CALL_TRANSACTION' + DESTINATION 'NONE' + STARTING NEW TASK 'ABAPGIT' + EXPORTING + tcode = iv_tcode + EXCEPTIONS + communication_failure = 1 MESSAGE lv_msg + system_failure = 2 MESSAGE lv_msg + OTHERS = 3. + IF sy-subrc <> 0. + lv_msg = |Error starting transaction { iv_tcode }: { lv_msg }|. + MESSAGE lv_msg TYPE 'I'. + ELSE. + lv_msg = |Transaction { iv_tcode } opened in a new window|. + MESSAGE lv_msg TYPE 'S'. + ENDIF. + + ENDMETHOD. + + METHOD db_actions. DATA ls_db_key TYPE zif_abapgit_persistence=>ty_content. @@ -680,6 +709,10 @@ CLASS zcl_abapgit_gui_router IMPLEMENTATION. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + WHEN zif_abapgit_definitions=>c_action-jump_transaction. + call_transaction( |{ ii_event->query( )->get( 'TRANSACTION' ) }| ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + WHEN zif_abapgit_definitions=>c_action-jump_transport. jump_display_transport( |{ ii_event->query( )->get( 'TRANSPORT' ) }| ). rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. diff --git a/src/ui/zabapgit_css_common.w3mi.data.css b/src/ui/zabapgit_css_common.w3mi.data.css index de06df247..708c7df74 100644 --- a/src/ui/zabapgit_css_common.w3mi.data.css +++ b/src/ui/zabapgit_css_common.w3mi.data.css @@ -74,6 +74,7 @@ span.separator { .w40 { width: 40%; } .float-right { float: right; } .pad-right { padding-right: 6px; } +.no-pad { padding: 0px !important; } .inline { display: inline; } .hidden { visibility: hidden; } .nodisplay { display: none } @@ -1550,4 +1551,4 @@ table.unit_tests { } .modal .radio-container label:hover { background-color: rgba(0, 0, 0, 0.1); -} +} \ No newline at end of file diff --git a/src/zif_abapgit_definitions.intf.abap b/src/zif_abapgit_definitions.intf.abap index 9ca1a0f26..08c678306 100644 --- a/src/zif_abapgit_definitions.intf.abap +++ b/src/zif_abapgit_definitions.intf.abap @@ -341,6 +341,7 @@ INTERFACE zif_abapgit_definitions homepage TYPE string VALUE 'homepage', ie_devtools TYPE string VALUE 'ie_devtools', jump TYPE string VALUE 'jump', + jump_transaction TYPE string VALUE 'jump_transaction', jump_transport TYPE string VALUE 'jump_transport', jump_user TYPE string VALUE 'jump_user', performance_test TYPE string VALUE 'performance_test',