Connexions SSH avec phpseclib et journal des actions

This commit is contained in:
Yasser Boulayoune 2026-04-07 13:19:00 +02:00
parent 52ecb4204c
commit f508a2fcb5
8 changed files with 11077 additions and 0 deletions

32
.gitignore vendored Normal file
View file

@ -0,0 +1,32 @@
###> symfony/framework-bundle ###
/.env.local
/.env.local.php
/.env.*.local
/config/secrets/prod/prod.decrypt.private.php
/public/bundles/
/var/
/vendor/
###< symfony/framework-bundle ###
###> phpunit/phpunit ###
/phpunit.xml
/.phpunit.cache/
###< phpunit/phpunit ###
###> symfony/asset-mapper ###
/public/assets/
/assets/vendor/
###< symfony/asset-mapper ###
# OS
.DS_Store
Thumbs.db
# IDE
.idea/
.vscode/
*.swp
*.swo
# Docker override local
compose.override.yaml

21
bin/console Executable file
View file

@ -0,0 +1,21 @@
#!/usr/bin/env php
<?php
use App\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application;
if (!is_dir(dirname(__DIR__).'/vendor')) {
throw new LogicException('Dependencies are missing. Try running "composer install".');
}
if (!is_file(dirname(__DIR__).'/vendor/autoload_runtime.php')) {
throw new LogicException('Symfony Runtime is missing. Try running "composer require symfony/runtime".');
}
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
return function (array $context) {
$kernel = new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
return new Application($kernel);
};

4
bin/phpunit Executable file
View file

@ -0,0 +1,4 @@
#!/usr/bin/env php
<?php
require dirname(__DIR__).'/vendor/phpunit/phpunit/phpunit';

10503
composer.lock generated Normal file

File diff suppressed because it is too large Load diff

121
deploy.sh Executable file
View file

@ -0,0 +1,121 @@
#!/bin/bash
# =============================================================================
# deploy.sh — Deploiement en production pour ServerControl
# Usage : ./deploy.sh (depuis la racine du projet, apres un git pull)
# =============================================================================
# ── Couleurs ──────────────────────────────────────────────────────────────────
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'
ok() { echo -e "${GREEN} [OK]${NC} $1"; }
info() { echo -e "${CYAN} [>>]${NC} $1"; }
warn() { echo -e "${YELLOW} [!!]${NC} $1"; }
fail() { echo -e "${RED} [ERR]${NC} $1"; exit 1; }
echo ""
echo -e "${CYAN} ======================================${NC}"
echo -e "${CYAN} ServerControl — Deploiement prod ${NC}"
echo -e "${CYAN} ======================================${NC}"
echo ""
# ── 0. Verifications ──────────────────────────────────────────────────────────
[ ! -f "bin/console" ] && fail "Lance ce script depuis la racine du projet Symfony."
command -v composer &>/dev/null || fail "Composer introuvable dans le PATH."
# detecter PHP : cherche php8.4 > php8.3 > php8.2 > php
PHP_BIN=""
for bin in php8.4 php8.3 php8.2 php; do
command -v "$bin" &>/dev/null && { PHP_BIN="$bin"; break; }
done
[ -z "$PHP_BIN" ] && fail "Aucun binaire PHP trouvé dans le PATH."
info "PHP détecté : $PHP_BIN ($($PHP_BIN -r 'echo PHP_VERSION;' 2>/dev/null))"
# verifier .env.local et proposer de le creer s'il manque
if [ ! -f ".env.local" ]; then
echo ""
warn ".env.local introuvable — ce fichier est obligatoire en production."
echo ""
read -p " Veux-tu le créer maintenant ? (o/N) " -n 1 -r; echo ""
if [[ $REPLY =~ ^[Oo]$ ]]; then
echo ""
read -p " DATABASE_URL (ex: postgresql://user:pass@127.0.0.1:5432/servercontrol?serverVersion=16&charset=utf8) : " DB_URL
read -p " APP_SECRET (chaine aleatoire, min 32 chars) : " APP_SEC
read -p " MAILER_DSN (ex: smtp://user:pass@sandbox.smtp.mailtrap.io:2525) : " MAILER
cat > .env.local <<EOF
APP_ENV=prod
APP_DEBUG=0
APP_SECRET=${APP_SEC}
DATABASE_URL="${DB_URL}"
MAILER_DSN="${MAILER}"
EOF
ok ".env.local crée."
else
fail "Abandonne. Crée .env.local puis relance le script."
fi
fi
# s'assurer que APP_ENV=prod est dans .env.local (sinon les commandes console tournent en dev)
if ! grep -q "APP_ENV=prod" .env.local; then
warn "APP_ENV=prod absent de .env.local — ajout automatique."
echo "APP_ENV=prod" >> .env.local
ok "APP_ENV=prod ajouté."
fi
export APP_ENV=prod
export APP_DEBUG=0
echo ""
# ── 1. Dependances Composer ───────────────────────────────────────────────────
info "Installation des dependances (sans dev, sans scripts)..."
# --no-scripts evite que les @auto-scripts Symfony tournent ici
# les warnings PHP deprecated de Composer sont redirigés vers /dev/null
composer install \
--no-dev \
--optimize-autoloader \
--no-interaction \
--no-scripts \
--quiet \
2>/dev/null
ok "Dependances installées."
# ── 2. Cache : suppression ────────────────────────────────────────────────────
info "Suppression du cache..."
# on supprime manuellement pour eviter les erreurs si le cache est corrompu
rm -rf var/cache/prod 2>/dev/null || true
$PHP_BIN bin/console cache:clear --env=prod --no-debug 2>&1 | grep -v "^$" | tail -2
ok "Cache supprimé."
# ── 3. Migrations base de données ─────────────────────────────────────────────
info "Migrations Doctrine..."
$PHP_BIN bin/console doctrine:migrations:migrate \
--no-interaction \
--env=prod \
2>&1 | grep -v "^\s*$"
ok "Migrations OK."
# ── 4. Assets (asset-mapper) ──────────────────────────────────────────────────
info "Compilation des assets..."
$PHP_BIN bin/console asset-map:compile --env=prod 2>&1 | grep -v "^\s*$" | tail -3
ok "Assets compilés."
# ── 5. Prechauffage du cache ──────────────────────────────────────────────────
info "Prechauffage du cache prod..."
$PHP_BIN bin/console cache:warmup --env=prod --no-debug 2>&1 | grep -v "^\s*$" | tail -2
ok "Cache prechauffé."
# ── 6. Permissions sur var/ ───────────────────────────────────────────────────
info "Permissions sur var/..."
chmod -R 775 var/ 2>/dev/null && ok "Permissions OK." || warn "Impossible de modifier var/ (pas grave si le webserver y a déjà accès)."
# ── 7. Redemarrage PHP-FPM ────────────────────────────────────────────────────
# Descommente la ligne correspondant a ta version de PHP sur le serveur :
# sudo systemctl restart php8.4-fpm && ok "php8.4-fpm redemarré." || warn "Echec restart php8.4-fpm."
# sudo systemctl restart php8.3-fpm && ok "php8.3-fpm redemarré." || warn "Echec restart php8.3-fpm."
# sudo systemctl restart php8.2-fpm && ok "php8.2-fpm redemarré." || warn "Echec restart php8.2-fpm."
echo ""
echo -e "${GREEN} ======================================${NC}"
echo -e "${GREEN} Deploiement terminé avec succès ! ${NC}"
echo -e "${GREEN} ======================================${NC}"
echo ""

44
phpunit.dist.xml Normal file
View file

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
colors="true"
failOnDeprecation="true"
failOnNotice="true"
failOnWarning="true"
bootstrap="tests/bootstrap.php"
cacheDirectory=".phpunit.cache"
>
<php>
<ini name="display_errors" value="1" />
<ini name="error_reporting" value="-1" />
<server name="APP_ENV" value="test" force="true" />
<server name="SHELL_VERBOSITY" value="-1" />
</php>
<testsuites>
<testsuite name="Project Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<source ignoreSuppressionOfDeprecations="true"
ignoreIndirectDeprecations="true"
restrictNotices="true"
restrictWarnings="true"
>
<include>
<directory>src</directory>
</include>
<deprecationTrigger>
<method>Doctrine\Deprecations\Deprecation::trigger</method>
<method>Doctrine\Deprecations\Deprecation::delegateTriggerToBackend</method>
<function>trigger_deprecation</function>
</deprecationTrigger>
</source>
<extensions>
</extensions>
</phpunit>

352
symfony.lock Normal file
View file

@ -0,0 +1,352 @@
{
"doctrine/deprecations": {
"version": "1.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.0",
"ref": "fdd756167454623e21f1d769c5b814b243782a67"
}
},
"doctrine/doctrine-bundle": {
"version": "3.2",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.0",
"ref": "d39a3bd844edfe90c20ae520b804a3bf4f82b4ad"
},
"files": [
"config/packages/doctrine.yaml",
"src/Entity/.gitignore",
"src/Repository/.gitignore"
]
},
"doctrine/doctrine-fixtures-bundle": {
"version": "4.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.0",
"ref": "1f5514cfa15b947298df4d771e694e578d4c204d"
},
"files": [
"src/DataFixtures/AppFixtures.php"
]
},
"doctrine/doctrine-migrations-bundle": {
"version": "4.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.1",
"ref": "1d01ec03c6ecbd67c3375c5478c9a423ae5d6a33"
},
"files": [
"config/packages/doctrine_migrations.yaml",
"migrations/.gitignore"
]
},
"knplabs/knp-paginator-bundle": {
"version": "v6.10.0"
},
"phpunit/phpunit": {
"version": "13.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "11.1",
"ref": "ca0bc067abfb40a8de1b2561b96cbfc2b833c314"
},
"files": [
".env.test",
"phpunit.dist.xml",
"tests/bootstrap.php",
"bin/phpunit"
]
},
"symfony/asset-mapper": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.4",
"ref": "c01c47af2ec66a74ec046eccb919cfe27d3464ec"
},
"files": [
"assets/app.js",
"assets/styles/app.css",
"config/packages/asset_mapper.yaml",
"importmap.php"
]
},
"symfony/console": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.3",
"ref": "1781ff40d8a17d87cf53f8d4cf0c8346ed2bb461"
},
"files": [
"bin/console"
]
},
"symfony/debug-bundle": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.3",
"ref": "5aa8aa48234c8eb6dbdd7b3cd5d791485d2cec4b"
},
"files": [
"config/packages/debug.yaml"
]
},
"symfony/flex": {
"version": "2.10",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "2.4",
"ref": "52e9754527a15e2b79d9a610f98185a1fe46622a"
},
"files": [
".env",
".env.dev"
]
},
"symfony/form": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.2",
"ref": "7d86a6723f4a623f59e2bf966b6aad2fc461d36b"
},
"files": [
"config/packages/csrf.yaml"
]
},
"symfony/framework-bundle": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.4",
"ref": "d5dcd308c8becd725c9d8b91e31aab1ff0bbc30b"
},
"files": [
"config/packages/cache.yaml",
"config/packages/framework.yaml",
"config/preload.php",
"config/routes/framework.yaml",
"config/services.yaml",
"public/index.php",
"src/Controller/.gitignore",
"src/Kernel.php",
".editorconfig"
]
},
"symfony/mailer": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "4.3",
"ref": "09051cfde49476e3c12cd3a0e44289ace1c75a4f"
},
"files": [
"config/packages/mailer.yaml"
]
},
"symfony/maker-bundle": {
"version": "1.67",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.0",
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
}
},
"symfony/messenger": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.0",
"ref": "d8936e2e2230637ef97e5eecc0eea074eecae58b"
},
"files": [
"config/packages/messenger.yaml"
]
},
"symfony/monolog-bundle": {
"version": "4.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.7",
"ref": "1b9efb10c54cb51c713a9391c9300ff8bceda459"
},
"files": [
"config/packages/monolog.yaml"
]
},
"symfony/notifier": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.0",
"ref": "178877daf79d2dbd62129dd03612cb1a2cb407cc"
},
"files": [
"config/packages/notifier.yaml"
]
},
"symfony/property-info": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.3",
"ref": "dae70df71978ae9226ae915ffd5fad817f5ca1f7"
},
"files": [
"config/packages/property_info.yaml"
]
},
"symfony/routing": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.4",
"ref": "bc94c4fd86f393f3ab3947c18b830ea343e51ded"
},
"files": [
"config/packages/routing.yaml",
"config/routes.yaml"
]
},
"symfony/security-bundle": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.4",
"ref": "c42fee7802181cdd50f61b8622715829f5d2335c"
},
"files": [
"config/packages/security.yaml",
"config/routes/security.yaml"
]
},
"symfony/stimulus-bundle": {
"version": "3.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "2.24",
"ref": "d21494ed2ddbde38942e8278299a23ce5cf4a9a1"
},
"files": [
"assets/controllers.json",
"assets/controllers/csrf_protection_controller.js",
"assets/controllers/hello_controller.js",
"assets/stimulus_bootstrap.js"
]
},
"symfony/translation": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.3",
"ref": "620a1b84865ceb2ba304c8f8bf2a185fbf32a843"
},
"files": [
"config/packages/translation.yaml",
"translations/.gitignore"
]
},
"symfony/twig-bundle": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.4",
"ref": "f250159ebe99153d0c640a3e7742876fc7453f2c"
},
"files": [
"config/packages/twig.yaml",
"templates/base.html.twig"
]
},
"symfony/ux-turbo": {
"version": "3.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "2.20",
"ref": "287f7c6eb6e9b65e422d34c00795b360a787380b"
},
"files": [
"config/packages/ux_turbo.yaml"
]
},
"symfony/validator": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.0",
"ref": "8c1c4e28d26a124b0bb273f537ca8ce443472bfd"
},
"files": [
"config/packages/validator.yaml"
]
},
"symfony/web-profiler-bundle": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.3",
"ref": "a363460c1b0b4a4d0242f2ce1a843ca0f6ac9026"
},
"files": [
"config/packages/web_profiler.yaml",
"config/routes/web_profiler.yaml"
]
},
"symfony/webapp-pack": {
"version": "1.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.0",
"ref": "b9e6cc8e7b6069d0e8a816665809a423864eb4dd"
},
"files": [
"config/packages/messenger.yaml"
]
},
"symfonycasts/reset-password-bundle": {
"version": "1.25",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.0",
"ref": "97c1627c0384534997ae1047b93be517ca16de43"
},
"files": [
"config/packages/reset_password.yaml"
]
},
"twig/extra-bundle": {
"version": "v3.24.0"
}
}

0
translations/.gitignore vendored Normal file
View file