Files
MYSOPHAL/inc/glpinetwork.class.php
2025-08-07 13:15:31 +01:00

316 lines
11 KiB
PHP

<?php
/**
* ---------------------------------------------------------------------
* GLPI - Gestionnaire Libre de Parc Informatique
* Copyright (C) 2015-2020 Teclib' and contributors.
*
* http://glpi-project.org
*
* based on GLPI - Gestionnaire Libre de Parc Informatique
* Copyright (C) 2003-2014 by the INDEPNET Development Team.
*
* ---------------------------------------------------------------------
*
* LICENSE
*
* This file is part of GLPI.
*
* GLPI is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GLPI is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GLPI. If not, see <http://www.gnu.org/licenses/>.
* ---------------------------------------------------------------------
*/
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access this file directly");
}
class GLPINetwork {
public function getTabNameForItem() {
return 'GLPI Network';
}
static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) {
if ($item->getType() == 'Config') {
$glpiNetwork = new self();
$glpiNetwork->showForConfig();
}
}
public static function showForConfig() {
if (!Config::canView()) {
return;
}
$registration_key = self::getRegistrationKey();
$canedit = Config::canUpdate();
if ($canedit) {
echo "<form name='form' action=\"".Toolbox::getItemTypeFormURL(Config::class)."\" method='post'>";
}
echo "<div class='center' id='tabsbody'>";
echo "<table class='tab_cadre_fixe'>";
echo "<tr><th colspan='2'>" . __('Registration') . "</th></tr>";
if ($registration_key === "") {
echo "<tr><td colspan='2'>".
__('A registration key is needed to use advanced feature (like marketplace) in GLPI')."<br><br>".
"<a href='".GLPI_NETWORK_SERVICES."'>".sprintf(__('Register on %1$s!'), 'GLPI Network')."</a><br>".
__("And retrieve your key to paste it below").
"</td></tr>";
}
$curl_error = null;
if (!self::isServicesAvailable($curl_error)) {
echo '<tr>';
echo '<td colspan="2">';
echo '<div class="warning">';
echo '<i class="fa fa-exclamation-triangle fa-2x"></i>';
echo sprintf(__("%1$s services website seems not available from your network or offline"), 'GLPI Network');
if ($curl_error !== null) {
echo '<br />';
echo sprintf(__('Error was: %s'), $curl_error);
}
echo '</div>';
echo '</td>';
echo '</tr>';
}
echo "<tr class='tab_bg_2'>";
echo "<td><label for='glpinetwork_registration_key'>" . __('Registration key') . "</label></td>";
echo "<td>" . Html::textarea(['name' => 'glpinetwork_registration_key', 'value' => $registration_key, 'display' => false]) . "</td>";
echo "</tr>";
if ($registration_key !== "") {
$informations = self::getRegistrationInformations();
if (!empty($informations['validation_message'])) {
echo "<tr class='tab_bg_2'>";
echo "<td></td>";
echo "<td>";
echo "<div class=' " . ($informations['is_valid'] ? 'ok' : 'red') . "'> ";
echo "<i class='fa fa-info-circle'></i>";
echo $informations['validation_message'];
echo "</div>";
echo "</td>";
echo "</tr>";
}
echo "<tr class='tab_bg_2'>";
echo "<td>" . __('Subscription') . "</td>";
echo "<td>" . ($informations['subscription'] !== null ? $informations['subscription']['title'] : __('Unknown')) . "</td>";
echo "</tr>";
echo "<tr class='tab_bg_2'>";
echo "<td>" . __('Registered by') . "</td>";
echo "<td>" . ($informations['owner'] !== null ? $informations['owner']['name'] : __('Unknown')) . "</td>";
echo "</tr>";
}
if ($canedit) {
echo "<tr class='tab_bg_2'>";
echo "<td colspan='2' class='center'>";
echo "<input type='submit' name='update' class='submit' value=\""._sx('button', 'Save')."\">";
echo "</td></tr>";
}
echo "</table></div>";
Html::closeForm();
}
/**
* Get GLPI User Agent in expected format from GLPI Network services.
*
* @return string
*/
public static function getGlpiUserAgent(): string {
$version = defined('GLPI_PREVER') ? GLPI_PREVER : GLPI_VERSION;
$comments = sprintf('installation-mode:%s', GLPI_INSTALL_MODE);
if (!empty(GLPI_USER_AGENT_EXTRA_COMMENTS)) {
// append extra comments (remove '(' and ')' chars to not break UA string)
$comments .= '; ' . preg_replace('/\(\)/', ' ', GLPI_USER_AGENT_EXTRA_COMMENTS);
}
return sprintf('GLPI/%s (%s)', $version, $comments);
}
/**
* Get GLPI Network UID to pass in requests to GLPI Network Services.
*
* @return string
*/
public static function getGlpiNetworkUid(): string {
return Config::getUuid('glpi_network');
}
/**
* Get GLPI Network registration key.
*
* A registration key is a base64 encoded JSON string with a key 'signature' containing the binary
* signature of the whole.
*
* @return string
*/
public static function getRegistrationKey(): string {
global $CFG_GLPI;
return Toolbox::sodiumDecrypt($CFG_GLPI['glpinetwork_registration_key'] ?? '');
}
/**
* Get GLPI Network registration informations.
*
* @return array Registration data:
* - is_valid (boolean): indicates if key is valid;
* - validation_message (string): message related to validation state;
* - owner (array): owner attributes;
* - subscription (array): subscription attributes.
*/
public static function getRegistrationInformations() {
global $GLPI_CACHE;
$registration_key = self::getRegistrationKey();
$cache_key = sprintf('registration_%s_informations', sha1($registration_key));
if (($informations = $GLPI_CACHE->get($cache_key)) !== null) {
return $informations;
}
$informations = [
'is_valid' => false,
'validation_message' => null,
'owner' => null,
'subscription' => null,
];
if ($registration_key === '') {
return $informations;
}
// Verify registration from registration API
$error_message = null;
$registration_response = Toolbox::callCurl(
rtrim(GLPI_NETWORK_REGISTRATION_API_URL, '/') . '/info',
[
CURLOPT_HTTPHEADER => [
'Accept:application/json',
'Content-Type:application/json',
'User-Agent:' . self::getGlpiUserAgent(),
'X-Registration-Key:' . $registration_key,
'X-Glpi-Network-Uid:' . self::getGlpiNetworkUid(),
]
],
$error_message
);
$registration_data = $error_message === null ? json_decode($registration_response, true) : null;
if ($error_message !== null || json_last_error() !== JSON_ERROR_NONE
|| !is_array($registration_data) || !array_key_exists('is_valid', $registration_data)) {
$informations['validation_message'] = __('Unable to fetch registration informations.');
Toolbox::logError(
'Unable to fetch registration informations.',
$error_message,
$registration_response
);
return $informations;
}
$informations['is_valid'] = $registration_data['is_valid'];
$informations['validation_message'] = $registration_data['is_valid']
? __('The registration key is valid.')
: __('The registration key is invalid.');
$informations['owner'] = $registration_data['owner'];
$informations['subscription'] = $registration_data['subscription'];
$GLPI_CACHE->set($cache_key, $informations, new \DateInterval('P1D')); // Cache for one day
return $informations;
}
/**
* Check if GLPI Network registration is existing and valid.
*
* @return boolean
*/
public static function isRegistered(): bool {
return self::getRegistrationInformations()['is_valid'];
}
public static function showInstallMessage() {
return nl2br(sprintf(__("You need help to integrate GLPI in your IT, have a bug fixed or benefit from pre-configured rules or dictionaries?\n\n".
"We provide the %s space for you.\n".
"GLPI-Network is a commercial product that includes a subscription for tier 3 support, ensuring the correction of bugs encountered with a commitment time.\n\n".
"In this same space, you will be able to <b>contact an official partner</b> to help you with your GLPI integration.\n\n".
"Or, support the GLPI development effort by <b>donating</b>."),
"<a href='".GLPI_NETWORK_SERVICES."' target='_blank'>".GLPI_NETWORK_SERVICES."</a>"));
}
public static function getErrorMessage() {
return nl2br(sprintf(__("Having troubles setting up an advanced GLPI module?\n".
"We can help you solve them. Sign up for support on %s."),
"<a href='".GLPI_NETWORK_SERVICES."' target='_blank'>".GLPI_NETWORK_SERVICES."</a>"));
}
public static function addErrorMessageAfterRedirect() {
Session::addMessageAfterRedirect(self::getErrorMessage(), false, ERROR);
}
/**
* Executes a curl call
*
* @param string $curl_error will contains original curl error string if an error occurs
*
* @return boolean
*/
public static function isServicesAvailable(&$curl_error = null) {
$error_msg = null;
$content = \Toolbox::callCurl(GLPI_NETWORK_REGISTRATION_API_URL, [], $error_msg, $curl_error);
return strlen($content) > 0;
}
public static function getOffers(bool $force_refresh = false): array {
global $GLPI_CACHE;
$lang = preg_replace('/^([a-z]+)_.+$/', '$1', $_SESSION["glpilanguage"]);
$cache_key = 'glpi_network_offers_' . $lang;
if (!$force_refresh && $GLPI_CACHE->has($cache_key)) {
return $GLPI_CACHE->get($cache_key);
}
$error_message = null;
$response = \Toolbox::callCurl(
rtrim(GLPI_NETWORK_REGISTRATION_API_URL, '/') . '/offers',
[
CURLOPT_HTTPHEADER => [
'Accept:application/json',
'Accept-Language: ' . $lang,
]
],
$error_message
);
$offers = $error_message === null ? json_decode($response) : null;
if ($error_message !== null || json_last_error() !== JSON_ERROR_NONE || !is_array($offers)) {
Toolbox::logError(
'Unable to fetch offers informations.',
$error_message,
$response
);
return [];
}
$GLPI_CACHE->set($cache_key, $offers, HOUR_TIMESTAMP);
return $offers;
}
}