<?php

/*
 * Copyright 2005 - 2025 Centreon (https://www.centreon.com/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * For more information : contact@centreon.com
 *
 */

session_start();
require_once __DIR__ . '/../../../../bootstrap.php';
require_once '../functions.php';

$return = [
    'id' => 'createuser',
    'result' => 1,
    'msg' => '',
];

$step = new CentreonLegacy\Core\Install\Step\Step6($dependencyInjector);
$parameters = $step->getDatabaseConfiguration();

try {
    $link = new PDO(
        'mysql:host=' . $parameters['address'] . ';port=' . $parameters['port'],
        $parameters['root_user'],
        $parameters['root_password']
    );
} catch (PDOException $e) {
    $return['msg'] = $e->getMessage();
    echo json_encode($return);

    exit;
}

$host = 'localhost';
// if database server is not on localhost...
if ($parameters['address'] != '127.0.0.1' && $parameters['address'] != 'localhost') {
    $getIpQuery = $link->prepare(
        'SELECT host FROM information_schema.processlist WHERE ID = connection_id()'
    );
    $getIpQuery->execute();
    // The result example (172.17.0.1:38216), use the explode function to remove port
    $host = explode(':', $getIpQuery->fetchAll(PDO::FETCH_COLUMN)[0])[0];
}

$queryValues = [
    ':dbUser' => $parameters['db_user'],
    ':host' => $host,
    ':dbPass' => $parameters['db_password'],
];

// Set defined privileges for the user.
$mandatoryPrivileges = [
    'SELECT',
    'UPDATE',
    'DELETE',
    'INSERT',
    'CREATE',
    'DROP',
    'INDEX',
    'ALTER',
    'LOCK TABLES',
    'CREATE TEMPORARY TABLES',
    'EVENT',
    'CREATE VIEW',
    'SHOW VIEW',
    'REFERENCES',
    'TRIGGER',
];
$privilegesQuery = implode(', ', $mandatoryPrivileges);
$query = 'GRANT ' . $privilegesQuery . " ON `%s`.* TO '" . $parameters['db_user'] . "'@'" . $host . "'";
$flushQuery = 'FLUSH PRIVILEGES';

try {
    $findUserStatement = $link->prepare('SELECT * FROM mysql.user WHERE User = :dbUser AND Host = :host');
    $findUserStatement->bindValue(':dbUser', $queryValues[':dbUser'], PDO::PARAM_STR);
    $findUserStatement->bindValue(':host', $queryValues[':host'], PDO::PARAM_STR);
    $findUserStatement->execute();
    // If user doesn't exist, create it
    if ($result = $findUserStatement->fetch(PDO::FETCH_ASSOC) === false) {
        // creating the user - mandatory for MySQL DB
        $prepareCreate = $link->prepare('CREATE USER :dbUser@:host IDENTIFIED BY :dbPass');
        foreach ($queryValues as $key => $value) {
            $prepareCreate->bindValue($key, $value, PDO::PARAM_STR);
        }
        // creating the user
        $prepareCreate->execute();

        // granting privileges
        $link->exec(sprintf($query, $parameters['db_configuration']));
        $link->exec(sprintf($query, $parameters['db_storage']));

        // enabling the new parameters
        $link->exec($flushQuery);
    } else {
        // If he exists check the right
        $privilegesStatement = $link->prepare('SHOW GRANTS FOR :dbUser@:host');
        $privilegesStatement->bindValue(':dbUser', $queryValues[':dbUser'], PDO::PARAM_STR);
        $privilegesStatement->bindValue(':host', $queryValues[':host'], PDO::PARAM_STR);
        $privilegesStatement->execute();

        // If rights are found
        $foundPrivilegesForCentreonDatabase = false;
        $foundPrivilegesForCentreonStorageDatabase = false;
        while ($result = $privilegesStatement->fetch(PDO::FETCH_ASSOC)) {
            foreach ($result as $grant) {
                // Format Grant result to get privileges list, and concerned database.
                if (preg_match('/^GRANT\s(?!USAGE)(.+)\sON\s?(.+)\.\*/', $grant, $matches)) {
                    // Check if privileges has been found for global (*) or centreon databases.
                    switch ($matches[2]) {
                        case '`' . $parameters['db_configuration'] . '`':
                            $foundPrivilegesForCentreonDatabase = true;
                            break;
                        case '`' . $parameters['db_storage'] . '`':
                            $foundPrivilegesForCentreonStorageDatabase = true;
                            break;
                        case '*':
                            $foundPrivilegesForCentreonStorageDatabase = true;
                            $foundPrivilegesForCentreonDatabase = true;
                            break;
                    }
                    $resultPrivileges = explode(', ', $matches[1]);

                    // Check that user has sufficient privileges to perform all needed actions.
                    $missingPrivileges = [];
                    if ($resultPrivileges[0] !== 'ALL PRIVILEGES') {
                        foreach ($mandatoryPrivileges as $mandatoryPrivilege) {
                            if (! in_array($mandatoryPrivilege, $resultPrivileges)) {
                                $missingPrivileges[] = $mandatoryPrivilege;
                            }
                        }
                        if ($missingPrivileges !== []) {
                            throw new Exception(
                                sprintf(
                                    'Missing privileges %s on user %s',
                                    implode(', ', $missingPrivileges),
                                    $queryValues[':dbUser']
                                )
                            );
                        }
                    }
                }
            }
        }
        if ($foundPrivilegesForCentreonDatabase === false || $foundPrivilegesForCentreonStorageDatabase === false) {
            throw new Exception(
                sprintf(
                    'No privileges for \'%s\' or \'%s\' databases for \'%s\' user has been found, '
                    . 'please check your MySQL configuration',
                    $parameters['db_configuration'],
                    $parameters['db_storage'],
                    $queryValues[':dbUser']
                )
            );
        }
    }
} catch (Exception $e) {
    $return['msg'] = $e->getMessage();
    echo json_encode($return);

    exit;
}
$return['result'] = 0;
echo json_encode($return);

exit;
