316 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			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;
 | |
|    }
 | |
| }
 |