Commit 7e96a44b authored by okhin's avatar okhin 🚴

Merge branch 'preprod' into 'master'

Mise en production

See merge request !37
parents 0185770e d131a2fc
/nbproject/private/
*~ *~
messages.pot messages.pot
locales/es_ES/LC_MESSAGES/messages.mo *.mo
locales/de_DE/LC_MESSAGES/messages.mo
locales/en_US/LC_MESSAGES/messages.mo
locales/fr_FR/LC_MESSAGES/messages.mo
locales/it_IT/LC_MESSAGES/messages.mo
/.tx/
#images/logo-lqdn-2.png
static/images/logo-lqdn.png
images/ids/
images/logo-[0-9]*.png
images/banner1.png
images/banner_fr_FR.png
images/banner_en_US.png
videos/
admin/.htaccess
admin/.htpasswd
pplome.* pplome.*
*.log *.log
tmp/* tmp/*
admin/tmp/*
piplomes/ piplomes/
CACHE/ CACHE/
vendor/ vendor/
pdf/ pdf/
/phinx.yml app/env
/app/env .php_cs.cache
.DS_Store
__MAC
tests/_output/* tests/_data
/var/log/* tests/_output
!/var/log/.gitkeep tests/_support/_generated
/.php_cs.cache
tests/*/_generated/*
...@@ -9,6 +9,7 @@ stages: ...@@ -9,6 +9,7 @@ stages:
job test: job test:
stage: test stage: test
variables: variables:
GIT_SUBMODULE_STRATEGY: normal
SQL_HOST: "localhost" SQL_HOST: "localhost"
SQL_PORT: "3306" SQL_PORT: "3306"
SQL_DATABASE: "test_$CI_BUILD_REF" SQL_DATABASE: "test_$CI_BUILD_REF"
...@@ -44,7 +45,7 @@ job test: ...@@ -44,7 +45,7 @@ job test:
- echo "SQL_DATABASE=${SQL_DATABASE}" >> app/env - echo "SQL_DATABASE=${SQL_DATABASE}" >> app/env
- make install - make install
- make server-start - make server-start
- make test - make -k test
- make server-stop - make server-stop
- mysql -u $SQL_USER -p$SQL_PASSWORD -e "DROP DATABASE $SQL_DATABASE" - mysql -u $SQL_USER -p$SQL_PASSWORD -e "DROP DATABASE $SQL_DATABASE"
tags: tags:
......
[submodule "www/static/pi-billion"]
path = www/static/pi-billion
url = https://git.laquadrature.net/lqdn-interne/pi-billion.git
...@@ -31,10 +31,16 @@ doctor: ## Check that everything is installed to use this application ...@@ -31,10 +31,16 @@ doctor: ## Check that everything is installed to use this application
@which msgfmt >/dev/null 2>&1 && echo "\033[32mmsgfmt installed\033[0m" || echo "\033[31mmsgfmt not installed\033[0m" @which msgfmt >/dev/null 2>&1 && echo "\033[32mmsgfmt installed\033[0m" || echo "\033[31mmsgfmt not installed\033[0m"
@which xgettext >/dev/null 2>&1 && echo "\033[32mxgettext installed\033[0m" || echo "\033[31mxgettext not installed\033[0m" @which xgettext >/dev/null 2>&1 && echo "\033[32mxgettext installed\033[0m" || echo "\033[31mxgettext not installed\033[0m"
@which pdftk >/dev/null 2>&1 && echo "\033[32mpdftk installed\033[0m" || echo "\033[31mpdftk not installed\033[0m" @which pdftk >/dev/null 2>&1 && echo "\033[32mpdftk installed\033[0m" || echo "\033[31mpdftk not installed\033[0m"
@test -s /usr/share/php7.0-xml/xml/dom.ini && echo "\033[032mphp-ext-dom installed\033[0m" || echo "\033[31mphp-ext-dom not installed (php-xml)\033[0m"
@test -s /usr/share/php7.0-zip/zip/zip.ini && echo "\033[032mphp-zip installed\033[0m" || echo "\033[31mphp-zip not installed\033[0m"
@test -s /usr/share/php7.0-mbstring/mbstring/mbstring.ini && echo "\033[032mphp-mbstring installed\033[0m" || echo "\033[31mphp-mbstring not installed\033[0m"
@test -s /usr/share/php7.0-curl/curl/curl.ini && echo "\033[032mphp-curl installed\033[0m" || echo "\033[31mphp-curl not installed\033[0m"
install: ## Install the application install: ## Install the application
@echo "\033[1m\033[36m==> Install Composer dependencies\033[0m\033[21m" @echo "\033[1m\033[36m==> Install Composer dependencies\033[0m\033[21m"
@composer -n install @composer -n install
@mkdir -p ./log
@mkdir -p ./tmp
reset-db: ## Install or re-install the DB reset-db: ## Install or re-install the DB
@echo "\033[1m\033[36m==> Drop database "$(SQL_DATABASE)" if it already exists\033[0m\033[21m" @echo "\033[1m\033[36m==> Drop database "$(SQL_DATABASE)" if it already exists\033[0m\033[21m"
...@@ -56,12 +62,16 @@ test-functional: ## Launch functional tests. ...@@ -56,12 +62,16 @@ test-functional: ## Launch functional tests.
@$(MAKE) reset-db @$(MAKE) reset-db
@./vendor/bin/codecept run functional @./vendor/bin/codecept run functional
coverage: ## Launch functional tests with coverage.
@$(MAKE) reset-db
@./vendor/bin/codecept run functional --coverage-html
server-start: server-stop ## Launch a local server server-start: server-stop ## Launch a local server
@php -S 127.0.0.1:8000 >> ./var/log/server.log & @php -S 127.0.0.1:8000 -t ./www/ >> ./log/server.log &
@echo "\033[32mServer running. (http://127.0.0.1:8000)\033[0m" @echo "\033[32mServer running. (http://127.0.0.1:8000)\033[0m"
server-stop: ## Stop local server if running server-stop: ## Stop local server if running
@ps -aux | grep "[p]hp -S 127.0.0.1:8000" | grep -v grep | awk '{print $$2}' | xargs -r -n 1 kill -@ps -aux | grep "[p]hp -S 127.0.0.1:8000" | grep -v grep | awk '{print $$2}' | xargs -r -n 1 kill
@echo "\033[32mServer stopped. (http://127.0.0.1:8000)\033[0m" @echo "\033[32mServer stopped. (http://127.0.0.1:8000)\033[0m"
cs-fix: ## Fix CS cs-fix: ## Fix CS
......
# LQDN soutien # LQDN soutien
## Installation This is a php application based on Fat-Free-Framework and a MySQL database that handles donations and presents offered to donors to La Quadrature du Net
It's used as our primary donation platform, and uses our bank's payment system (cheaper) to get one-time or recurring payments recorded into the donation platform.
## Installation (quick)
In order to install this project, run `make doctor` to check that everything is fine. In order to install this project, run `make doctor` to check that everything is fine.
...@@ -19,3 +23,52 @@ To access to the admin (`/admin`) use `admin`/`password` ...@@ -19,3 +23,52 @@ To access to the admin (`/admin`) use `admin`/`password`
## Contributing ## Contributing
Before submitting a PR, makes sure tests are OK: `make test` Before submitting a PR, makes sure tests are OK: `make test`
# Detailed dependencies, installation ...
## Dependencies
This software depends on a few software :
* **composer** (to install php dependencies) see https://getcomposer.org/
* a **mysql client** (to inject the database schema)
* a **mysql server** (no need for it to be local)
* **pdftk** to generate pi-plomes (pdf with pi's decimals offered to our donors)
* **texlive-latex-base** for the `pdflatex` binary for the piplomes (only required in production or for people debugging the piplomes code)
and for developers you may also need :
* **xgettext** to manage translations, use:
* `make messages.pot` to update PO files from source code.
* `make translations` to compile MO files from PO files when translations are ready.
This software uses:
* **PHP5.6** currently (migration to PHP7.x is in the pipe)
* **phinx** to inject database schema and initial data / accounts into MySQL see https://phinx.org/
* **php-cs-fixer** to check php code for errors and fix coding standard issues, see https://github.com/FriendsOfPHP/PHP-CS-Fixer
* **doctrine/dbal** as ORM see https://github.com/doctrine/dbal
* **f3 framework** as main view / controller framework. see https://fatfreeframework.com/
Look at `app/` folder for most Controllers, and `app/routes.ini` for the application routes (the URLs)
# Production deployment (not finished)
* `app/env` must contains the proper values : database connection, bank visa payment codes, and ENV=production at the bottom.
* point your Nginx or Apache with PHP5.6 to the `www/` folder, and either allow Rewrite Rules (a2enmod rewrite) or point every URL not being a file to index.php (see below for an nginx sample)
* use AND FORCE https usage, it's 2018, people ;)
Nginx configuration sample:
```
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php5.sock;
}
location / {
# try to serve file directly, fallback to index.php
try_files $uri /index.php$is_args$args;
}
```
...@@ -19,9 +19,9 @@ Cette fonction définit un mot de passe de 12 caractères ...@@ -19,9 +19,9 @@ Cette fonction définit un mot de passe de 12 caractères
} }
/* /*
Cette fonction cherche à nettoyer un mauvais encodage en utf-8. Cette fonction cherche à nettoyer un mauvais encodage en utf-8.
*/ */
public static function clean_encoding($string) public static function clean_encoding($string)
{ {
$bad_encoding = array("é","à ","è","ç","ë","ô","î","ù"); $bad_encoding = array("é","à ","è","ç","ë","ô","î","ù");
......
[globals] [globals]
; Répertoire contenant les classes chargées dynamiquement ; Répertoire contenant les classes chargées dynamiquement
AUTOLOAD=app/ AUTOLOAD=../app/
; Répertoire contenant les templates ; Répertoire contenant les templates
UI=templates/ UI=../app/view/
; Répertoire des fichiers temporaires
TEMP=../tmp/
; Répertoire des logs ; Répertoire des logs
LOGS=tmp LOGS=../log/
; Gestionnaire d'erreur personnalisé ; Gestionnaire d'erreur personnalisé
; ONERROR="Main->error" ; ONERROR="Main->error"
......
...@@ -46,6 +46,14 @@ define("SMTP_PW", getenv('SMTP_PW')); ...@@ -46,6 +46,14 @@ define("SMTP_PW", getenv('SMTP_PW'));
define("DEBUG", getenv('DEBUG')); define("DEBUG", getenv('DEBUG'));
define("SENTRY", getenv('SENTRY'));
$sentry_client = new Raven_Client($SENTRY);
$error_handler = new Raven_ErrorHandler($sentry_client);
$error_handler->registerExceptionHandler();
$error_handler->registerErrorHandler();
$error_handler->registerShutdownFunction();
if ('prod' !== $env) { if ('prod' !== $env) {
error_reporting(E_ALL|E_WARNING); error_reporting(E_ALL|E_WARNING);
ini_set("display_errors", true); ini_set("display_errors", true);
......
This diff is collapsed.
<?php <?php
namespace Controller;
class Bank extends Controller class Bank extends Controller
{ {
/* We want to ignore the sanitizing on this page */ /* We want to ignore the sanitizing on this page */
public function sanitizeForms($f3) public function sanitizeForms($f3)
{ {
return; return;
} }
/* /*
Page de retour de la banque Page de retour de la banque
*/ */
...@@ -14,7 +15,7 @@ class Bank extends Controller ...@@ -14,7 +15,7 @@ class Bank extends Controller
{ {
@include_once("config.php"); @include_once("config.php");
$cb_log = new Log('/cb.log'); $cb_log = new \Log('/cb.log');
$error=""; $error="";
$result = $f3->get('POST.vads_result'); $result = $f3->get('POST.vads_result');
$status = $f3->get('POST.vads_trans_status'); $status = $f3->get('POST.vads_trans_status');
...@@ -80,9 +81,11 @@ class Bank extends Controller ...@@ -80,9 +81,11 @@ class Bank extends Controller
$sig .= $value . "+"; $sig .= $value . "+";
} }
$sig .= CERTIFICATE; $sig .= CERTIFICATE;
$cb_log->write("sig: " . $signature . " == " . sha1($sig)); ### Attempt to do it in hmac-sha256
if (sha1($sig)!=$signature) { $sig_hash = base64_encode(hash_hmac('sha256', $sig, CERTIFICATE, true));
$error = "Error in signature: " . $signature . " != " . sha1($sig); $cb_log->write("sig: " . $signature . " == " . $sig_hash);
if ($sig_hash!=$signature) {
$error = "Error in signature: " . $signature . " != " . $sig_hash;
} }
// Résultats des vérifications globales // Résultats des vérifications globales
if ($error!="") { if ($error!="") {
...@@ -106,7 +109,7 @@ class Bank extends Controller ...@@ -106,7 +109,7 @@ class Bank extends Controller
$id = intval($order_id); $id = intval($order_id);
$cb_log->write("Id: ".$order_id); $cb_log->write("Id: ".$order_id);
$res = $db->query("SELECT * FROM dons WHERE id='".$id."';"); $res = $db->query("SELECT * FROM dons WHERE id='".$id."';");
$don = $res->fetch(PDO::FETCH_ASSOC); $don = $res->fetch(\PDO::FETCH_ASSOC);
if (!$don) { if (!$don) {
$cb_log->write("Transaction id not found: ".$order_id); $cb_log->write("Transaction id not found: ".$order_id);
...@@ -144,11 +147,11 @@ class Bank extends Controller ...@@ -144,11 +147,11 @@ class Bank extends Controller
// ok, somme OK, status = completed, transaction found. // ok, somme OK, status = completed, transaction found.
$db->query("UPDATE dons SET status=status+1 WHERE id='".$id."';"); $db->query("UPDATE dons SET status=status+1 WHERE id='".$id."';");
$res = $db->query("SELECT status FROM dons WHERE id='".$id."';"); $res = $db->query("SELECT status FROM dons WHERE id='".$id."';");
$status = $res->fetch(PDO::FETCH_ASSOC); $status = $res->fetch(\PDO::FETCH_ASSOC);
$status = $status['status']; $status = $status['status'];
$res = $db->query("SELECT * FROM users WHERE id='".$don['user_id']."';"); $res = $db->query("SELECT * FROM users WHERE id='".$don['user_id']."';");
$user = $res->fetch(PDO::FETCH_ASSOC); $user = $res->fetch(\PDO::FETCH_ASSOC);
$cb_log->write("Utilisation d'un utilisateur existant"); $cb_log->write("Utilisation d'un utilisateur existant");
// Ajout du nouveau don au cumul actuel // Ajout du nouveau don au cumul actuel
if ($status!=101) { if ($status!=101) {
...@@ -156,7 +159,7 @@ class Bank extends Controller ...@@ -156,7 +159,7 @@ class Bank extends Controller
$db->query("UPDATE users set cumul = cumul + " . $don['somme'] . ", total = total + " . $don['somme'] . " WHERE id='".$don['user_id']."'"); $db->query("UPDATE users set cumul = cumul + " . $don['somme'] . ", total = total + " . $don['somme'] . " WHERE id='".$don['user_id']."'");
} }
$result = $db->query("SELECT cumul FROM users WHERE id='".$don['user_id']."'"); $result = $db->query("SELECT cumul FROM users WHERE id='".$don['user_id']."'");
$cumul = $result->fetch(PDO::FETCH_ASSOC); $cumul = $result->fetch(\PDO::FETCH_ASSOC);
$cumul = $cumul['cumul']; $cumul = $cumul['cumul'];
$cb_log->write("Nouveau cumul: ".$cumul); $cb_log->write("Nouveau cumul: ".$cumul);
$user_id = $user['id']; $user_id = $user['id'];
...@@ -167,7 +170,7 @@ class Bank extends Controller ...@@ -167,7 +170,7 @@ class Bank extends Controller
// Puis envoi du mail // Puis envoi du mail
if ($user["email"]) { if ($user["email"]) {
$mailer = new SMTP(SMTP_HOST, SMTP_PORT, SMTP_SECURITY, SMTP_USER, SMTP_PW); $mailer = new \SMTP(SMTP_HOST, SMTP_PORT, SMTP_SECURITY, SMTP_USER, SMTP_PW);
$cb_log->write("Sending email for id: ".$id." at ".$user['email']); $cb_log->write("Sending email for id: ".$id." at ".$user['email']);
$mailer->set('From', "contact@laquadrature.net"); $mailer->set('From', "contact@laquadrature.net");
$mailer->set('FromName', "La Quadrature du Net"); $mailer->set('FromName', "La Quadrature du Net");
...@@ -195,21 +198,21 @@ Encore merci pour votre soutien, ...@@ -195,21 +198,21 @@ Encore merci pour votre soutien,
Toute l'équipe de La Quadrature du Net Toute l'équipe de La Quadrature du Net
")."\n\n"; ")."\n\n";
// Création de l'url d'administration // Création de l'url d'administration
$admin_url = "https://support.laquadrature.net/perso"; $admin_url = "https://support.laquadrature.net/perso";
foreach ($f3->get('languages') as $key => $language) { foreach ($f3->get('languages') as $key => $language) {
if ($lang==$language[1]) { if ($lang==$language[1]) {
$admin_url = "https://".$language[0].$f3->get('dev').".laquadrature.net/perso"; $admin_url = "https://".$language[0].$f3->get('dev').".laquadrature.net/perso";
} }
} }
// Remplacement des variables par leurs valeurs // Remplacement des variables par leurs valeurs
$fields = array( $fields = array(
"NAME"=>$user["pseudo"], "NAME"=>$user["pseudo"],
"SOMME"=>$don['somme'], "SOMME"=>$don['somme'],
"CUMUL"=>$cumul, "CUMUL"=>$cumul,
"URL_ADMIN" => $admin_url "URL_ADMIN" => $admin_url
); );
foreach ($fields as $k=>$v) { foreach ($fields as $k=>$v) {
$text = str_replace("%%".$k."%%", $v, $text); $text = str_replace("%%".$k."%%", $v, $text);
} }
......
<?php <?php
namespace Controller;
class Campaign extends Controller class Campaign extends Controller
{ {
/* /*
Page principale du site Page principale du site
*/ */
public function beforeRoute($f3, $args)
{
parent::beforeRoute($f3, $args);
// Valeur par défaut du bloc de contenu
$f3->set('block_content', 'campaign/empty.html');
// Get the database
$f3->set('SESSION.errors', []);
}
public function afterRoute($f3, $args)
{
parent::afterRoute($f3, $args);
// Rendu HTML de la page
echo Template::instance()->render('campaign/base.html');
}
public static function show($f3, $args) public static function show($f3, $args)
{ {
// Let's do some math first // Let's do some math first
// So, get the $db // So, get the $db
$db = $f3->get('DB'); $db = $f3->get('DB');
// Number of month left for a one-year provisionning since CAMPAIGN_START_DATE // Number of month left for a one-year provisionning since CAMPAIGN_START_DATE
$now = new DateTime('now'); $now = new \DateTime('now');
$start = new DateTime(CAMPAIGN_START_DATE); $start = new \DateTime(CAMPAIGN_START_DATE);
if ($start > $now) { if ($start > $now) {
$months = 0; $months = 0;
} else { } else {
...@@ -40,7 +23,8 @@ class Campaign extends Controller ...@@ -40,7 +23,8 @@ class Campaign extends Controller
$total_provisional = 0; $total_provisional = 0;
// So now, let's get the amount of confirmed dons, which are all the 1, 4, 101 and 102 // So now, let's get the amount of confirmed dons, which are all the 1, 4, 101 and 102
// statuses since CAMPAIGN_START_DATE // statuses since CAMPAIGN_START_DATE
$result = $db->query("SELECT SUM(somme) $result = $db->query(
"SELECT SUM(somme)
AS total_confirmed AS total_confirmed
FROM dons FROM dons
WHERE status IN (1, 4, 102) WHERE status IN (1, 4, 102)
...@@ -73,26 +57,7 @@ class Campaign extends Controller ...@@ -73,26 +57,7 @@ class Campaign extends Controller
// Page d'attente // Page d'attente
public function wait($f3) public function wait($f3)
{ {
echo Template::instance()->render('campaign/wait.html'); $f3->set('block_content', 'campaign/wait.html');
exit;
}
// Que fait la Quadrature ?
public function what($f3)
{
$f3->set('block_content', 'campaign/what.html');
}
// Comment fonctionne la Quadrature ?
public function who($f3)
{
$f3->set('block_content', 'campaign/who.html');
}
// À quoi servent les dons ?
public function why($f3)
{
$f3->set('block_content', 'campaign/why.html');
} }
// FAQ donateurs // FAQ donateurs
...@@ -101,16 +66,6 @@ class Campaign extends Controller ...@@ -101,16 +66,6 @@ class Campaign extends Controller
$f3->set('block_content', 'campaign/faq.html'); $f3->set('block_content', 'campaign/faq.html');
} }