# Appel REST depuis le contrôleur de session `libs`

Ce document décrit le remplacement de l'appel legacy :

```text
/serveruser/index.php
  methode=testLog
  param=<json>
  apikey=<cle>
```

par un appel REST direct :

```text
POST /api/v1/auth/login
Content-Type: application/json
X-API-Key: <cle>
```

Note : la route `/api/v1/auth/login` n'exige pas d'authentification côté API,
mais le même client PHP doit transmettre `X-API-Key` pour les autres routes
REST protégées. Le contrôleur ci-dessous applique donc le même mécanisme
d'authentification partout.

## Configuration `libs`

Dans `/mnt/One/web/beta/libs/config/config.ini` :

```ini
[general]
apikey = "<VOTRE_CLE_API>"

[servers]
api[default] = "http://beta.tnk/rcapi/api/v1"
```

La clé ne doit pas être versionnée dans le dépôt. Elle doit correspondre à une
entrée déclarée côté `rcapi` :

```bash
RCWS_API_KEYS='facts:<VOTRE_CLE_API>'
```

## Contrôleur PHP REST

Ce fichier conserve le contrat HTTP appelé par le JavaScript actuel :

```text
POST /libs/controller/sessioncontroller-api.php
methode=testLog
param={"login":"...","domaine":1,"password":"..."}
```

Il ne passe pas par `/serveruser/index.php`.

```php
<?php

declare(strict_types=1);

session_start();

header('Content-Type: text/html; charset=UTF-8');
date_default_timezone_set('Europe/Paris');
error_reporting(E_ALL);

function ecrireLog(string $var, string $qui): void
{
    global $log;

    $dir = $log . '/sessions';
    if (!is_dir($dir)) {
        mkdir($dir, 0775, true);
    }

    file_put_contents(
        $dir . '/' . date('Y-m-d') . '-session.log',
        date('H:i:s') . ', ' . $qui . " :\n\t" . $var . "\n",
        FILE_APPEND
    );
}

function eraseLogs(string $rep, string $datePurge): void
{
    if (!is_dir($rep)) {
        return;
    }

    foreach (array_slice(scandir($rep), 2) as $value) {
        $nom = substr((string) $value, 0, 10);
        $fichier = $rep . '/' . $value;

        if (!is_dir($fichier) && date('Y-m-d', strtotime($nom)) < $datePurge) {
            unlink($fichier);
        }
    }
}

function rcApiBaseUrl(): string
{
    global $rc, $libs_rc_default;

    if (!empty($rc['servers']['api']['default'])) {
        return rtrim((string) $rc['servers']['api']['default'], '/');
    }

    if (!empty($libs_rc_default['servers']['api']['default'])) {
        return rtrim((string) $libs_rc_default['servers']['api']['default'], '/');
    }

    $legacyUrl = (string) ($rc['servers']['adresse']['default'] ?? $libs_rc_default['servers']['adresse']['default']);

    return rtrim(str_replace('/serveruser/index.php', '/api/v1', $legacyUrl), '/');
}

/**
 * @param array<string, mixed> $payload
 *
 * @return array<string, mixed>
 */
function rcApiRequest(string $method, string $path, array $payload = []): array
{
    global $apiKey;

    if ($apiKey === '') {
        throw new RuntimeException('Cle API absente dans config.ini');
    }

    $ch = curl_init(rcApiBaseUrl() . '/' . ltrim($path, '/'));
    curl_setopt_array($ch, [
        CURLOPT_CUSTOMREQUEST => strtoupper($method),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'Accept: application/json',
            'Content-Type: application/json',
            'X-API-Key: ' . $apiKey,
        ],
        CURLOPT_TIMEOUT => 15,
    ]);

    if ($payload !== []) {
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
    }

    $body = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

    if ($body === false) {
        $error = curl_error($ch);
        curl_close($ch);
        throw new RuntimeException('Erreur cURL API RCWS: ' . $error);
    }

    curl_close($ch);

    $decoded = json_decode((string) $body, true);

    if (!is_array($decoded)) {
        throw new RuntimeException('Reponse JSON invalide depuis API RCWS');
    }

    if ($status >= 400) {
        $message = $decoded['error']['message'] ?? 'Erreur API RCWS';
        throw new RuntimeException((string) $message);
    }

    return $decoded;
}

function closeIt(string $function, string $jsonObj): string
{
    session_unset();
    session_destroy();
    ecrireLog('session destroyed', $function);

    return 'session destroyed';
}

function testLog(string $function, string $jsonObj): string
{
    try {
        $payload = json_decode($jsonObj, true);

        if (!is_array($payload)) {
            session_destroy();
            return 'invalid payload';
        }

        $response = rcApiRequest('POST', '/auth/login', $payload);
        $users = $response['data']['user'] ?? false;

        if (!is_array($users) || $users === []) {
            session_destroy();
            return 'no user registered';
        }

        $_SESSION['ok'] = true;
        $retour = '';

        foreach ($users as $user) {
            if (!is_array($user)) {
                continue;
            }

            foreach ($user as $cle => $value) {
                $_SESSION[(string) $cle] = $value;
                $retour .= $cle . ' => ' . $value . ' ';
            }
        }

        return $retour;
    } catch (Throwable $e) {
        session_destroy();
        ecrireLog($e->getMessage(), $function);

        return 'fatal error';
    }
}

$log = $_SERVER['DOCUMENT_ROOT'] . '/log';
$rc = parse_ini_file(__DIR__ . '/../config/config.ini', true);
$libs_rc_default = parse_ini_file(__DIR__ . '/../config/config-default.ini', true);
$apiKey = (string) ($rc['general']['apikey'] ?? $libs_rc_default['general']['apikey'] ?? '');
$datePurge = date('Y-m-d', strtotime(date('Y-m-d') . ' - 7 DAY'));

if (!is_dir($log)) {
    mkdir($log, 0775, true);
}

if (!is_dir($log . '/sessions')) {
    mkdir($log . '/sessions', 0775, true);
}

eraseLogs($log, $datePurge);
eraseLogs($log . '/sessions', $datePurge);

if (isset($_REQUEST['methode'], $_REQUEST['param'])) {
    $methode = (string) $_REQUEST['methode'];
    $params = (string) $_REQUEST['param'];

    if (!function_exists($methode)) {
        session_destroy();
        http_response_code(400);
        echo 'unknown method';
        exit;
    }

    echo call_user_func_array($methode, [$methode, $params]);
}
```

## Test REST direct

```bash
curl -i \
  -X POST \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  --data '{"login":"<LOGIN>","domaine":1,"password":"<MOT_DE_PASSE>"}' \
  http://beta.tnk/rcapi/api/v1/auth/login
```

Pour une route protégée :

```bash
curl -i \
  -H 'Accept: application/json' \
  -H 'X-API-Key: <VOTRE_CLE_API>' \
  http://beta.tnk/rcapi/api/v1/domains/1/users
```
