Commit 78c11e0b authored by Stephane Bouvry's avatar Stephane Bouvry
Browse files

Normalisation de l'API en cours

parent b739c1c9
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -129,6 +129,8 @@ data/templates/custom.inc.php

# PHPUnit
tests/.phpunit.result.cache
tests/test-api.env


# Residus
public/js/oscar/dist/index.html
+2 −2
Original line number Diff line number Diff line
@@ -296,9 +296,9 @@ class AbstractOscarController extends AbstractActionController implements UseOsc
        return $this->jsonError($error);
    }

    protected function jsonError( string $msg ) :Response
    protected function jsonError( string $msg, $code = Response::STATUS_CODE_500 ) :Response
    {
        return $this->getResponseInternalError($msg);
        return $this->getHttpResponse($code, $msg);
    }

    protected function getPutDataJson() :Parameters
+32 −27
Original line number Diff line number Diff line
@@ -4,8 +4,8 @@ namespace Oscar\Controller;

use BjyAuthorize\Exception\UnAuthorizedException;
use Doctrine\DBAL\Driver\PDO\Exception;
use Laminas\Http\Response;
use Oscar\Entity\Activity;
use Oscar\Entity\ActivityType;
use Oscar\Entity\Person;
use Oscar\Entity\ProjectPartner;
use Oscar\Exception\OscarException;
@@ -160,8 +160,10 @@ class ApiController extends AbstractOscarController implements UseOscarUserConte
                    $strategies = json_decode($this->params()->fromPost('strategies'), JSON_OBJECT_AS_ARRAY);
                    if( array_key_exists($login, $datas) ){
                        $pass_show = $datas[$login]['pass_show'];
                        $pass_clean = $datas[$login]['pass_clean'];
                        $hash = $datas[$login]['pass'];
                    } else {
                        $pass_clean = $pass;
                        $pass_show = substr($pass,0,3)
                            . '...'
                            . substr($pass,strlen($pass)-3);
@@ -171,6 +173,7 @@ class ApiController extends AbstractOscarController implements UseOscarUserConte
                        'login' => $login,
                        'pass' => $hash,
                        'pass_show' => $pass_show,
                        'pass_clean' => $pass_clean,
                        'apis' => explode(',', $apis),
                        'strategies' => $strategies
                    ];
@@ -215,22 +218,22 @@ class ApiController extends AbstractOscarController implements UseOscarUserConte

        if (!$authHeader) {
            $this->getLoggerService()->error("[OSCAR API] Missing X-API-Key header");
            throw new UnAuthorizedException("[OSCAR API] Missing X-API-Key header", 401);
            throw new UnAuthorizedException("[OSCAR API] Missing X-API-Key header", Response::STATUS_CODE_400);
        }

        $token = $authHeader->getFieldValue();

        try {
            $infos = $this->getOscarConfigurationService()->getApiInfos($token);
        } catch (\Exception $e) {
            $this->getLoggerService()->error("[OSCAR API] Erreur d'accès : " . $e->getMessage());
            throw new OscarException("[OSCAR API] Accès interdit à l'API Oscar (Bad key)", Response::STATUS_CODE_403);
        }
        if( !in_array($api, $infos['apis']) ) {
            $this->getLoggerService()->error("[OSCAR API] Accès '$api' interdit");
                throw new OscarException("La clef n'autorise pas '$api'");
            throw new OscarException("La clef n'autorise pas l'accès : '$api'", Response::STATUS_CODE_405);
        }
        return $infos;
        } catch (\Exception $e) {
            $this->getLoggerService()->error("[OSCAR API] Erreur d'accès : " . $e->getMessage());
            throw new OscarException("[OSCAR API] Accès interdit à l'API Oscar");
        }
    }


@@ -272,25 +275,23 @@ class ApiController extends AbstractOscarController implements UseOscarUserConte
            switch ($method) {
                case "GET":
                    $this->checkApiAcces(self::ACCESS_PERSONS_INDEX);
                    return $this->personsActionGet();
                    break;
                case "POST":
                    throw new Exception("Non fait");
                    break;
                case "PUT":
                    throw new Exception("Non fait");
                    throw new \Exception("Creation d'une nouvelle ressource (Non fait)", Response::STATUS_CODE_501);
                    break;
                default:
                    throw new \Exception("Indisponible", Response::STATUS_CODE_404);
            }
        } catch (\Exception $e) {
            return $this->jsonError($e->getMessage());
            return $this->jsonError($e->getMessage(), $e->getCode());
        }
    }


        die($method);

    protected function personsActionGet()
    {
        try {
            $granted = $this->checkApiAcces('persons');
            $strategy = $this->getStrategy('persons');
            $personToJsonFormatter = new $strategy;
            $personToJsonFormatter = new PersonToJsonConnectorFormatter();
            $persons = [];

            /** @var Person $p */
@@ -298,26 +299,30 @@ class ApiController extends AbstractOscarController implements UseOscarUserConte
                $persons[] = $personToJsonFormatter->format($p);
            }

            $datas = [
                "version" => OscarVersion::getBuild(),
                "datecreated" => date('c'),
                'time' => (microtime(true) - $start),
                'total' => count($persons),
                'persons' => $persons
            ];
            $datas = $this->jsonOutputBase();
            $datas['total'] = count($persons);
            $datas['persons'] = $persons;

            return $this->jsonOutput($datas);
        } catch (\Exception $e) {
            return $this->getResponseUnauthorized($e->getMessage());
            return $this->jsonError($e->getMessage(), Response::STATUS_CODE_500);
        }
    }

    protected function jsonOutputBase() :array {
        return [
            "version" => OscarVersion::getBuild(),
            "datecreated" => date('c')
        ];
    }


    public function personAction()
    {
        $method = $this->getRequest()->getMethod();
        $this->checkApiAcces(self::ACCESS_PERSONS_GET);
        switch ($method) {
            case "GET":
                $this->checkApiAcces(self::ACCESS_PERSONS_GET);
                $id = $this->params()->fromRoute('id');
                if( $id ){
                    $access = self::ACCESS_PERSONS_GET;
+10 −0
Original line number Diff line number Diff line
API_BASE_URL="http://localhost:8888"
ENDPOINT="/api"

# Clés API (exemples)
API_KEY_NOT_EXIST="JENEXISTEPAS"
API_KEY_VALID="CLEF VALIDE ICI"
API_KEY_NO_RIGHT="CLEF VALIDE MAIS SANS ACCESS"

# Timeout curl
CURL_TIMEOUT=10
 No newline at end of file

tests/test-api.sh

0 → 100644
+107 −0
Original line number Diff line number Diff line
#!/usr/bin/env bash

# =========================
# Configuration
# =========================

source test-api.env

# =========================
# Couleurs
# =========================

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

# =========================
# Fonction de test générique
# =========================

run_test() {
    local name="$1"
    local method="$2"
    local url="$3"
    local expected_code="$4"
    shift 4


    body_tmp="$(mktemp)"

    echo "#########################################################################"
    echo -e "### TEST : ${name}"

    # La commande
    cmd=(
        curl -s
        -o "$body_tmp"
        -w "%{http_code}"
        -X "$method"
        "$@"
        "$url"
    )

    # On affiche
    echo "CMD: ${cmd[*]}"

    # On execute
    response="$("${cmd[@]}")"
    body="$(cat "$body_tmp")"
    rm -f "$body_file"

    if [[ "$response" == "$expected_code" ]]; then
        echo -e "${GREEN}✔ OK ${NC} (HTTP $response)"
    else
        echo -e "${RED}✘ KO ${NC} (HTTP '$response' attendu: $expected_code)"
        echo "---"
        echo $body
        echo ""
    fi
}


# =========================
# Tests
# =========================

run_test \
    "Sans clé API (entête manquante)" \
    "GET" \
    "${API_BASE_URL}${ENDPOINT}/persons" \
    "400"

run_test \
  "La clef n'existe pas" \
  "GET" \
  "${API_BASE_URL}${ENDPOINT}/persons" \
  "403" \
  -H "X-API-Key: JENESUISPASUNCLEFVALIDE"

run_test \
  "Clé valide sans droits" \
  "GET" \
  "${API_BASE_URL}${ENDPOINT}/persons" \
  "405" \
  -H "X-API-Key: ${API_KEY_NO_RIGHT}"

run_test \
    "Clé valide avec droits" \
    "GET" \
    "${API_BASE_URL}${ENDPOINT}/persons" \
    "200" \
    -H "X-API-Key: ${API_KEY_VALID}"

run_test \
    "Clé valide (méthode non disponible)" \
    "PUT" \
    "${API_BASE_URL}${ENDPOINT}/persons" \
    "404" \
    -H "X-API-Key: ${API_KEY_VALID}"

run_test \
    "Clé valide (méthode non-faite)" \
    "POST" \
    "${API_BASE_URL}${ENDPOINT}/persons" \
    "501" \
    -H "X-API-Key: ${API_KEY_VALID}"