Skip to content

Commit

Permalink
Block saving webhook responses
Browse files Browse the repository at this point in the history
  • Loading branch information
cconard96 authored Dec 16, 2024
1 parent f59177b commit 4eacccd
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 67 deletions.
6 changes: 0 additions & 6 deletions .phpstan-baseline.php
Original file line number Diff line number Diff line change
Expand Up @@ -2335,12 +2335,6 @@
'count' => 1,
'path' => __DIR__ . '/src/Glpi/Application/ErrorHandler.php',
];
$ignoreErrors[] = [
'message' => '#^Offset \'GLPI_AJAX_DASHBOARD\'\\|\'GLPI_ALLOW_IFRAME…\'\\|\'GLPI_CACHE_DIR\'\\|\'GLPI_CALDAV_IMPORT…\'\\|\'GLPI_CENTRAL…\'\\|\'GLPI_CONFIG_DIR\'\\|\'GLPI_CRON_DIR\'\\|\'GLPI_DISABLE_ONLY…\'\\|\'GLPI_DOC_DIR\'\\|\'GLPI_DOCUMENTATION…\'\\|\'GLPI_ENVIRONMENT…\'\\|\'GLPI_GRAPH_DIR\'\\|\'GLPI_INSTALL_MODE\'\\|\'GLPI_INVENTORY_DIR\'\\|\'GLPI_LOCAL_I18N_DIR\'\\|\'GLPI_LOCK_DIR\'\\|\'GLPI_LOG_DIR\'\\|\'GLPI_MARKETPLACE…\'\\|\'GLPI_MARKETPLACE_DIR\'\\|\'GLPI_NETWORK_MAIL\'\\|\'GLPI_NETWORK…\'\\|\'GLPI_PICTURE_DIR\'\\|\'GLPI_PLUGIN_DOC_DIR\'\\|\'GLPI_RSS_DIR\'\\|\'GLPI_SERVERSIDE_URL…\'\\|\'GLPI_SESSION_DIR\'\\|\'GLPI_TELEMETRY_URI\'\\|\'GLPI_TEXT_MAXSIZE\'\\|\'GLPI_THEMES_DIR\'\\|\'GLPI_TMP_DIR\'\\|\'GLPI_UPLOAD_DIR\'\\|\'GLPI_USER_AGENT…\'\\|\'GLPI_VAR_DIR\'\\|\'PLUGINS_DIRECTORIES\' on array\\{\\} on left side of \\?\\? does not exist\\.$#',
'identifier' => 'nullCoalesce.offset',
'count' => 2,
'path' => __DIR__ . '/src/Glpi/Application/SystemConfigurator.php',
];
$ignoreErrors[] = [
'message' => '#^Instanceof between DBmysql and DBmysql will always evaluate to true\\.$#',
'identifier' => 'instanceof.alwaysTrue',
Expand Down
4 changes: 2 additions & 2 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ parameters:
- GLPI_DISABLE_ONLY_FULL_GROUP_BY_SQL_MODE
- GLPI_DOC_DIR
- GLPI_DOCUMENTATION_ROOT_URL
- GLPI_ENVIRONMENT_TYPE
- GLPI_FORCE_MAIL
- GLPI_GRAPH_DIR
- GLPI_INSTALL_MODE
Expand Down Expand Up @@ -53,10 +54,9 @@ parameters:
- GLPI_THEMES_DIR
- GLPI_TMP_DIR
- GLPI_UPLOAD_DIR
- GLPI_USE_CSRF_CHECK
- GLPI_USE_IDOR_CHECK
- GLPI_USER_AGENT_EXTRA_COMMENTS
- GLPI_VAR_DIR
- GLPI_WEBHOOK_ALLOW_RESPONSE_SAVING
- PLUGINS_DIRECTORIES
- TU_USER
ignoreErrors:
Expand Down
4 changes: 3 additions & 1 deletion src/Glpi/Application/SystemConfigurator.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ private function computeConstants(): void
'GLPI_AJAX_DASHBOARD' => '1', // 1 for "multi ajax mode" 0 for "single ajax mode" (see Glpi\Dashboard\Grid::getCards)
'GLPI_CALDAV_IMPORT_STATE' => 0, // external events created from a caldav client will take this state by default (0 = Planning::INFO)
'GLPI_CENTRAL_WARNINGS' => '1', // display (1), or not (0), warnings on GLPI Central page
'GLPI_TEXT_MAXSIZE' => '4000' // character threshold for displaying read more button
'GLPI_TEXT_MAXSIZE' => '4000', // character threshold for displaying read more button
'GLPI_WEBHOOK_ALLOW_RESPONSE_SAVING' => '0', // allow (1) or not (0) to save webhook response in database
],
'production' => [
],
Expand All @@ -141,6 +142,7 @@ private function computeConstants(): void
],
],
'development' => [
'GLPI_WEBHOOK_ALLOW_RESPONSE_SAVING' => '1'
],
];

Expand Down
15 changes: 14 additions & 1 deletion src/QueuedWebhook.php
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,11 @@ public static function sendById(int $ID): bool
];
if ($response !== null) {
$input['last_status_code'] = $response->getStatusCode();
if ($queued_webhook->fields['save_response_body']) {
if (GLPI_WEBHOOK_ALLOW_RESPONSE_SAVING && $queued_webhook->fields['save_response_body']) {
$input['response_body'] = (string)$response->getBody();
} else {
// Save to property that won't be saved in DB, but can still be available to plugins
$input['_response_body'] = (string)$response->getBody();
}

if ($webhook->fields['log_in_item_history']) {
Expand Down Expand Up @@ -628,4 +631,14 @@ public static function cronQueuedWebhookClean(?CronTask $task = null)
$task->setVolume($vol);
return ($vol > 0 ? 1 : 0);
}

public function post_getFromDB()
{
parent::post_getFromDB();

if (!GLPI_WEBHOOK_ALLOW_RESPONSE_SAVING) {
// Block viewing response body if saving is disabled by config
unset($this->fields['response_body']);
}
}
}
2 changes: 2 additions & 0 deletions stubs/glpi_constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

// This file contains stubs for GLPI constants.
// Please try to keep them alphabetically ordered.
// Keep in sync with the dynamicConstantNames config option in the PHPStan config file

// Directories constants
define('GLPI_CACHE_DIR', null);
Expand Down Expand Up @@ -83,4 +84,5 @@
define('GLPI_TELEMETRY_URI', null);
define('GLPI_TEXT_MAXSIZE', null);
define('GLPI_USER_AGENT_EXTRA_COMMENTS', null);
define('GLPI_WEBHOOK_ALLOW_RESPONSE_SAVING', 0);
define('PLUGINS_DIRECTORIES', ['/a', '/b', '/c']);
114 changes: 58 additions & 56 deletions templates/pages/setup/webhook/queuedwebhook.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -37,68 +37,70 @@
{% set rand_field = rand|default(random()) %}

{% set params = params|merge({
addbuttons: {
send: {
icon: 'ti ti-send',
text: item.fields['last_status_code'] is null or item.fields['last_status_code'] >= 300 ? __('Send') : __('Resend'),
type: 'button'
}
}
addbuttons: {
send: {
icon: 'ti ti-send',
text: item.fields['last_status_code'] is null or item.fields['last_status_code'] >= 300 ? __('Send') : __('Resend'),
type: 'button'
}
}
}) %}

{% block form_fields %}
{{ fields.htmlField('itemtype', item.fields['itemtype'], _n('Type', 'Types', 1)) }}
{{ fields.htmlField('items_id', get_item_link(item.fields['itemtype'], item.fields['items_id']), _n('Item', 'Items', 1)) }}
{{ fields.htmlField('webhooks_id', get_item_link(webhook), 'Webhook'|itemtype_name) }}
{{ fields.nullField() }}
{{ fields.htmlField('create_time', item.fields['create_time'], __('Creation date')) }}
{{ fields.htmlField('send_time', item.fields['send_time'], __('Expected send date')) }}
{{ fields.htmlField('sent_time', item.fields['sent_time'], __('Send date')) }}
{{ fields.htmlField('sent_try', item.fields['sent_try'], __('Number of tries of sent')) }}
{{ fields.htmlField('last_status_code', item.getStatusCodeBadge(item.fields['last_status_code']), __('Last status code')) }}
{{ fields.htmlField('itemtype', item.fields['itemtype'], _n('Type', 'Types', 1)) }}
{{ fields.htmlField('items_id', get_item_link(item.fields['itemtype'], item.fields['items_id']), _n('Item', 'Items', 1)) }}
{{ fields.htmlField('webhooks_id', get_item_link(webhook), 'Webhook'|itemtype_name) }}
{{ fields.nullField() }}
{{ fields.htmlField('create_time', item.fields['create_time'], __('Creation date')) }}
{{ fields.htmlField('send_time', item.fields['send_time'], __('Expected send date')) }}
{{ fields.htmlField('sent_time', item.fields['sent_time'], __('Send date')) }}
{{ fields.htmlField('sent_try', item.fields['sent_try'], __('Number of tries of sent')) }}
{{ fields.htmlField('last_status_code', item.getStatusCodeBadge(item.fields['last_status_code']), __('Last status code')) }}

{{ fields.smallTitle(__('Request')) }}
{{ fields.smallTitle(__('Request')) }}

{{ fields.htmlField('url', item.fields['url'], __('URL')) }}
{{ fields.textareaField('body', item.fields['body'], '', {
full_width: true,
readonly: true,
rows: 10,
no_label: true,
}) }}
{{ fields.htmlField('url', item.fields['url'], __('URL')) }}
{{ fields.textareaField('body', item.fields['body'], '', {
full_width: true,
readonly: true,
rows: 10,
no_label: true,
}) }}

{{ fields.smallTitle(__('Headers')) }}
{% for header_name, header_value in headers %}
{{ fields.htmlField('headers_' ~ header_name, header_value, header_name) }}
{% endfor %}
{{ fields.smallTitle(__('Headers')) }}
{% for header_name, header_value in headers %}
{{ fields.htmlField('headers_' ~ header_name, header_value, header_name) }}
{% endfor %}

{{ fields.smallTitle(__('Last response')) }}
{{ fields.textareaField('response_body', item.fields['response_body'], '', {
full_width: true,
readonly: true,
rows: 10,
no_label: true,
}) }}
{% if constant('GLPI_WEBHOOK_ALLOW_RESPONSE_SAVING') %}
{{ fields.smallTitle(__('Last response')) }}
{{ fields.textareaField('response_body', item.fields['response_body'], '', {
full_width: true,
readonly: true,
rows: 10,
no_label: true,
}) }}
{% endif %}

<script>
$(() => {
$('button[name="send"]').click((e) => {
const btn = $(e.target);
$.ajax({
url: '{{ path('/ajax/webhook.php') }}',
type: 'POST',
data: {
'action': 'resend',
'id': {{ item.fields['id'] }}
},
beforeSend: () => {
btn.attr('disabled', true);
},
complete: () => {
window.location.reload();
}
});
});
})
</script>
<script>
$(() => {
$('button[name="send"]').click((e) => {
const btn = $(e.target);
$.ajax({
url: '{{ path('/ajax/webhook.php') }}',
type: 'POST',
data: {
'action': 'resend',
'id': {{ item.fields['id'] }}
},
beforeSend: () => {
btn.attr('disabled', true);
},
complete: () => {
window.location.reload();
}
});
});
})
</script>
{% endblock %}
4 changes: 3 additions & 1 deletion templates/pages/setup/webhook/webhook.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,9 @@
field_options
) }}

{{ fields.dropdownYesNo('save_response_body', item.fields['save_response_body'], __('Save response body')) }}
{% if constant('GLPI_WEBHOOK_ALLOW_RESPONSE_SAVING') %}
{{ fields.dropdownYesNo('save_response_body', item.fields['save_response_body'], __('Save response body')) }}
{% endif %}

{{ fields.dropdownYesNo('log_in_item_history', item.fields['log_in_item_history'], __('Log in item history')) }}

Expand Down

0 comments on commit 4eacccd

Please sign in to comment.