improve functionanility in register

- validate post request according to bussiness rules besides redundant
validation on front-end.
- validate captcha againts google service
- register every error in flash message service
- build json response for errors on submit
- add google/recaptcha to project and implements it, make settings for
secret-key, put test re-captcha in register.html and secret-test in
settings.
- add flash message service and register against container.
- add twig extension to read flash message service
- remove api folder from public, conflicts in routes.
This commit is contained in:
German Correa 2017-12-08 19:04:18 -03:00
parent 61d954d5fc
commit 507ea9a7ac
9 changed files with 223 additions and 277 deletions

View File

@ -3,7 +3,7 @@
"description": "Groups Geometry and Dynamics, ICM2018 Satellite, Web Project",
"keywords": ["ICM2018", "GGDWorkshop", "Montevideo","Math","Groups","Geometry"],
"homepage": "https://ggdworkshop.cmat.edu.uy",
"license": "GPLv3",
"license": "GPLv2",
"authors": [
{
"name": "Germán Correa",
@ -16,7 +16,8 @@
"slim/slim": "^3.1",
"monolog/monolog": "^1.17",
"slim/twig-view": "^2.3",
"google/recaptcha": "^1.1"
"google/recaptcha": "^1.1",
"kanellov/slim-twig-flash": "^0.2.0"
},
"require-dev": {
"phpunit/phpunit": ">=4.8 < 6.0"

105
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "f85f941c60254a0fb9e6426933aeac77",
"content-hash": "9a62d6d00b747b3976c6fb52bdeaeab3",
"packages": [
{
"name": "container-interop/container-interop",
@ -82,6 +82,61 @@
],
"time": "2017-03-09T18:44:34+00:00"
},
{
"name": "kanellov/slim-twig-flash",
"version": "0.2.0",
"source": {
"type": "git",
"url": "https://github.com/kanellov/slim-twig-flash.git",
"reference": "14a96919cfb116aa528b6ce9a611f544ac6d6a01"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/kanellov/slim-twig-flash/zipball/14a96919cfb116aa528b6ce9a611f544ac6d6a01",
"reference": "14a96919cfb116aa528b6ce9a611f544ac6d6a01",
"shasum": ""
},
"require": {
"php": ">=5.5.0",
"slim/flash": ">=0.1.0",
"twig/twig": ">=1.18"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "1.*",
"phpunit/phpcov": "2.*",
"phpunit/phpunit": "4.8.0",
"satooshi/php-coveralls": "dev-master"
},
"type": "library",
"autoload": {
"psr-4": {
"Knlv\\Slim\\Views\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"GNU GPLv3"
],
"authors": [
{
"name": "Vassilis Kanellopoulos",
"email": "contact@kanellov.com",
"homepage": "http://kanellov.com"
}
],
"description": "A Twig extension to access Slim Flash messages in templates",
"keywords": [
"extension",
"flash",
"framework",
"message",
"provider",
"slim",
"twig",
"view"
],
"time": "2016-12-29T22:07:19+00:00"
},
{
"name": "monolog/monolog",
"version": "1.23.0",
@ -399,6 +454,54 @@
],
"time": "2016-10-10T12:19:37+00:00"
},
{
"name": "slim/flash",
"version": "0.4.0",
"source": {
"type": "git",
"url": "https://github.com/slimphp/Slim-Flash.git",
"reference": "9aaff5fded3b54f4e519ec3d4ac74d3d1f2cbbbc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slimphp/Slim-Flash/zipball/9aaff5fded3b54f4e519ec3d4ac74d3d1f2cbbbc",
"reference": "9aaff5fded3b54f4e519ec3d4ac74d3d1f2cbbbc",
"shasum": ""
},
"require": {
"php": ">=5.5.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Slim\\Flash\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Josh Lockhart",
"email": "hello@joshlockhart.com",
"homepage": "http://joshlockhart.com"
}
],
"description": "Slim Framework Flash message service provider",
"homepage": "http://slimframework.com",
"keywords": [
"flash",
"framework",
"message",
"provider",
"slim"
],
"time": "2017-10-22T10:35:05+00:00"
},
{
"name": "slim/slim",
"version": "3.9.2",

View File

@ -1,76 +0,0 @@
<?php
function verifyCaptcha(){
$url = 'https://www.google.com/recaptcha/api/siteverify';
$data = array(
'secret' => '6LeLxy4UAAAAABClplWLJUjZ1_nhX_-SI7CuNcm8',
'response' => $_POST["g-recaptcha-response"]
);
$options = array(
'http' => array (
'header' => 'Content-Type: application/x-www-form-urlencoded\r\n',
'method' => 'POST',
'content' => http_build_query($data)
)
);
$context = stream_context_create($options);
$verify = file_get_contents($url, false, $context);
$captcha_success=json_decode($verify);
return $captcha_success;
}
// process.php
$errors = array(); // array to hold validation errors
$data = array(); // array to pass back data
// validate the variables ======================================================
// if any of these variables don't exist, add an error to our $errors array
if (empty($_POST['nombre']))
$errors['nombre'] = 'Name is required.';
if (empty($_POST['email']))
$errors['email'] = 'Email is required.';
if (empty($_POST['mensage']))
$errors['mensage'] = 'Mensaje is required.';
if(empty($_POST['g-recaptcha-response'])){
$errors['recaptcha'] = 'Debe validar el captcha';
}
else if(!verifyCaptcha()){
$errors['recaptcha'] = 'Error en la validación de ReCaptcha';
}
// return a response ===========================================================
// if there are any errors in our errors array, return a success boolean of false
if ( ! empty($errors)) {
// if there are items in our errors array, return those errors
$data['success'] = false;
$data['errors'] = $errors;
} else {
// if there are no errors process our form, then return a message
// DO ALL YOUR FORM PROCESSING HERE
// THIS CAN BE WHATEVER YOU WANT TO DO (LOGIN, SAVE, UPDATE, WHATEVER)
// show a message of success and provide a true success variable
$nombre = $_POST['nombre'];
$mail = $_POST['email'];
$msg = $_POST['mensage'];
$headers = 'From: ' . $mail . "\r\n" .
'Reply-To: ' . $mail . "\r\n" .
'X-Mailer: PHP/' . phpversion();
mail('6coloquio@cmat.edu.uy', 'Contacto de ' . $nombre, $msg, $headers);
$data['success'] = true;
$data['message'] = 'Mensaje enviado,<br/>A la brevedad el comite organizador se pondrá en contacto con usted.';
}
// return all our data to an AJAX call
echo json_encode($data);
?>

View File

@ -1,135 +0,0 @@
<?php
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
include_once $root.'/db/db.php';
function verifyCaptcha(){
$url = 'https://www.google.com/recaptcha/api/siteverify';
$data = array(
'secret' => '6LesRDsUAAAAAA6t3UgL4U4Foc9njmXX-8HIiLj_',
'response' => $_POST["g-recaptcha-response"]
);
$options = array(
'http' => array (
'header' => 'Content-Type: application/x-www-form-urlencoded\r\n',
'method' => 'POST',
'content' => http_build_query($data)
)
);
$context = stream_context_create($options);
$verify = file_get_contents($url, false, $context);
$captcha_success=json_decode($verify);
return $captcha_success;
}
/*function verifyExistance($doc,$mail){
$fp = fopen("2021y22.csv", 'r');
fclose($fp);
}*/
/*function setheaders() {
$fp = fopen("2021y22.csv", 'w');
$cabezal = array('Nombre', 'Apellido','TipoDoc','Documento',
'Direccion','Pais','Ciudad', 'Telefono', 'Email',
'Profesión','Trabaja en','Financiación','Detalle Financiación');
if($fp){
fputcsv($fp,$cabezal);
fclose($fp);
}
else{
die("unable to open file");
}
}*/
/*function registrar($fila) {
$fp = fopen("2021y22.csv", 'a');
if($fp){
fputcsv($fp,$fila);
fclose($fp);
}
else{
die("unable to open file");
}
}
function bkpregister(){
$fecha = date("d-m-H:i:s");
$filebkp = "bkp/registro-".$fecha.".bak.csv";
copy("2021y22.csv",$filebkp);
}*/
$errors = array(); // array to hold validation errors
$data = array(); // array to pass back data
// validate the variables ======================================================
$data['nombre'] = $_POST['nombre'];
$data['apellido'] = $_POST['apellido'];
$data['titulo'] = $_POST['titulo'];
$data['afiliacion'] = $_POST['afiliacion'];
$data['ciudad'] = $_POST['ciudad'];
$data['pais'] = $_POST['pais'];
$data['email'] = $_POST['email'];
$data['fechaLlegada'] = $_POST['bda'];
$data['fechaPartida'] = $_POST['eda'];
$data['financiacion'] = $_POST['financiacion'];
$data['invitado'] = $_POST['invited'];
$data['cartaInvitacion'] = $_POST['letterinvited'];
$data['roomingPref'] = $_POST['roomtype'];
$data['roommate'] = $_POST['roomate'];
$data['fechaRegistro'] = date("Y-m-d H:i:s");
$fila = $data;
if (empty($_POST['nombre']))
$errors['nombre'] = 'Nombre is required.';
if (empty($_POST['apellido']))
$errors['apellido'] = 'Apellido is required.';
if (empty($_POST['email']))
$errors['email'] = 'E-Mail de contacto vacio o incorrecto';
if(empty($_POST['g-recaptcha-response'])){
$errors['recaptcha'] = 'Debe validar el captcha';
}
else if(!verifyCaptcha()){
$errors['recaptcha'] = 'Error en la validación de ReCaptcha';
}
/*GUAMBIA ACAAA!!!!*/
$errors=array();
/* NO GILEAR!!!!!*/
if ( !empty($errors)) {
// if there are items in our errors array, return those errors
$data['success'] = false;
$data['errors'] = $errors;
}
else {
$data['success'] = true;
$db->insert($fila);
/*
$mail = $data["email"];
$nombre = $data["nombre"] . " " . $data["apellido"];
$msg = "Hi ". $data["nombre"] ."!\n\n".
"You have been Successfully registered to the workshop on Groups, Geometry and Dynamics!\n\n".
"For any question, write us to: ggdworkshop@cmat.edu.uy\n\n".
"Regards,\n\n".
"Organizing Commite, GGD Workshop.";
$headers = 'From: ' . "ggdworkshop@cmat.edu.uy" . "\r\n" .
'Reply-To: ' . "ggdworkshop@cmat.edu.uy" . "\r\n" .
'Content-Type: ' . "text/plain; charset=UTF-8". "\r\n" .
'X-Mailer: PHP/' . phpversion();
mail($mail, 'Registration confirmation for GGDWorkshop', $msg, $headers);
*/
$data['message'] = "Registration Successfully!";
}
// return all our data to an AJAX call
echo json_encode($data);
?>

View File

@ -3,25 +3,35 @@
$container = $app->getContainer();
$container['flash'] = function($c){
return new \Slim\Flash\Messages();
};
$container['renderer'] = function ($c) {
$settings = $c->get('settings')['renderer'];
return new Slim\Views\Twig($settings['template_path'],[
$view = new Slim\Views\Twig($settings['template_path'],[
'cache' => $settings['cache_path'],
]);
$view->addExtension(new Knlv\Slim\Views\TwigMessages(
$c->get('flash')
));
return $view;
};
$container['db'] = function ($c) {
$db = $c->get('settings')['db'];
try{
$pdo = new PDO('sqlite:'.$db['path']);
$pdo->setAttribute( \PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION );
$pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
$pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
}
catch(\PDOException $e){
echo $e->getMessage();
}
return $pdo;
};
// monolog

View File

@ -26,7 +26,7 @@ $app->get('/registration', function (Request $request, Response $response, array
$app->get('/participants', function (Request $request, Response $response, array $args) {
// Sample log message
$this->logger->info("GDDWorkshop '/participants' route");
$db = new DB($this->db);
$db = new DB($this->db);
$data = $db->getAll();
// Render index view
@ -39,6 +39,7 @@ $app->get('/committess', function (Request $request, Response $response, array $
$this->logger->info("GDDWorkshop '/committess' route");
// Render index view
//$this->flash->addMessage("lele","mensaje de lele");
return $this->renderer->render($response, 'committess.html', $args);
});
@ -47,10 +48,10 @@ $mw = function ($request, $response, $next) {
$response->getBody()->write('BEFORE');
$response = $next($request, $response);
$response->getBody()->write('AFTER');
return $response;
};*/
// API ROUTES
$app->group('/api', function($app){
@ -63,21 +64,52 @@ $app->group('/api', function($app){
$app->post('/register', function (Request $request, Response $response, array $args) {
// Sample log message
//$this->logger->debug(var_dump($request->getParsedBody()));
$db = new DB($this->db);
$db = new DB($this->db);
$data = $request->getParsedBody();
$messages = $this->flash;
if(!isset($data['nombre']))
$messages->addMessageNow("submit-register-err", "First Name could not be empty");
if(!isset($data['apellido']))
$messages->addMessageNow("submit-register-err", "Last Name could not be empty");
if(!isset($data['email']))
$messages->addMessageNow("submit-register-err", "E-mail could not be empty");
if(!isset($data['financiacion']))
$messages->addMessageNow("submit-register-err", "Question about financial support must have a selected answer");
if(!isset($data['invited']))
$messages->addMessageNow("submit-register-err", "Question about 'invited to participate in this conference' must have a selected answer");
if(!isset($data['letterinvited']))
$messages->addMessageNow("submit-register-err", "Question about needing a letter of invitation must have a selected answer");
if(!isset($data['g-recaptcha-response'])){
$messages->addMessageNow("submit-register-err", "Please validate captcha!");
}
else {
$recaptcha = new ReCaptcha\ReCaptcha($this->settings['recaptcha']['secret-test']);
//get remote ip from request header TODO
$resp = $recaptcha->verify($data['g-recaptcha-response'], $_SERVER['REMOTE_ADDR']);
if(!$resp->isSuccess()){
$messages->addMessageNow("submit-register-err", "ReCaptcha validation error " . implode($resp->getErrorCodes()));
}
}
try{
$db->insert($data);
}
catch (Exception $e){
$this->logger->debug($e->getMessage());
return $e->getMessage();
}
if($messages->hasMessage("submit-register-err")){
$arrayresponse = array("success" => false, "errors"=>$messages->getMessage("submit-register-err"), "data"=>$data);
$newres = $response->withJson($arrayresponse);
return $newres;
}
else {
/*try{
$db->insert($data);
}
catch (Exception $e){
$this->logger->debug($e->getMessage());
return $e->getMessage();
}*/
echo "todo ok";
}
$newresponse = $response->withJson($data);
return $newresponse;
});
});
});

View File

@ -4,7 +4,7 @@ return [
'displayErrorDetails' => true, // set to false in production
'addContentLengthHeader' => false, // Allow the web server to send the content-length header
'debug' => true,
// Renderer settings
'renderer' => [
'template_path' => __DIR__ . '/../templates/',
@ -21,7 +21,11 @@ return [
'level' => \Monolog\Logger::DEBUG,
],
'db' => [
'path' => __DIR__."/../db/ggdworkshop.db"
'path' => __DIR__."/../db/ggdworkshop.db",
],
'recaptcha' => [
'secret' => "6LesRDsUAAAAAA6t3UgL4U4Foc9njmXX-8HIiLj_",
'secret-test' => "6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe",
],
],
];

View File

@ -4,7 +4,7 @@
<div class="row">
<div class="col-xs-12">
<h1><strong>Committees</strong></h1>
<h1><strong>Committees</strong></h1>
<h2>Scientific Committee</h2>
<ul class="comite">
<li><a href="http://www.math.lsa.umich.edu/~canary/" data-linktype="external" data-val="http://www.math.lsa.umich.edu/~canary/">Dick Canary - University of Michigan</a></li>
@ -23,7 +23,7 @@
<li>Andrés Sambarino</li>
<li>Martín Sambarino</li>
</ul>
</div>
</div>
{% endblock %}
{% endblock %}

View File

@ -6,13 +6,13 @@
<h1>Registration</h1>
<form id="registerform" method="POST" action novalidate="novalidate">
<form id="registerform" method="POST" action novalidate="novalidate">
<!-- Nombre y Apellido -->
<div class="row">
<div class="form-group col-xs-12 col-sm-6">
<label class="control-label" for="nombre">First Name</label>
<div class="input-container">
<input id="nombre" class="form-control" name="nombre" type="text">
<input id="nombre" class="form-control" name="nombre" type="text">
</div>
</div>
@ -29,11 +29,11 @@
<div class="form-group col-xs-12 col-sm-6">
<label class="control-label" for="titulo">Title</label>
<div class="input-container">
<input id="titulo" class="form-control" name="titulo"
<input id="titulo" class="form-control" name="titulo"
placeholder="Professor, Post Doc, Grad Student(1st year, 2nd year, etc..)" type="text">
</div>
</div>
<div class="form-group col-xs-12 col-sm-6">
<label class="control-label " for="afiliacion">Affiliation</label>
<div class="input-container">
@ -48,18 +48,18 @@
<div class="form-group col-xs-12 col-sm-6">
<label class=" control-label" for="ciudad">City</label>
<div class="input-container">
<input id="ciudad" name="ciudad" class="form-control" type="text">
</div>
<input id="ciudad" name="ciudad" class="form-control" type="text">
</div>
</div>
<div class="form-group col-xs-12 col-sm-6">
<label class=" control-label" for="pais">Country</label>
<div class="input-container">
<div class="input-container">
<select id="pais" name="pais">
<option></optoon>
</select>
</div>
</select>
</div>
</div>
</div>
@ -68,7 +68,7 @@
<div class="form-group col-xs-12">
<label class="control-label" for="email">Email</label>
<div class="input-container">
<input id="email" class="form-control" name="email"
<input id="email" class="form-control" name="email"
placeholder="mail@example.com" type="email">
</div>
</div>
@ -81,25 +81,25 @@
<div class="input-container">
<input id="txtbda" class="form-control" placeholder="DD/MM/AAAA" name="bda">
</div>
</div>
</div>
<div class="form-group col-xs-12 col-sm-6">
<label class="control-label " for="txteda">Ending date attending</label>
<div class="input-container">
<input id="txteda" class="form-control" placeholder="DD/MM/AAAA" name="eda">
</div>
</div>
</div>
</div>
<!-- Financial Support -->
<div class="row">
<div class="form-group col-xs-12">
<label class="control-label" for="sifinan">
Are you asking for support from the conference?
Are you asking for support from the conference?
</label>
<div class="radios input-container">
<label class="radio-inline"><input id="sifinan" type="radio" name="financiacion" value="1">Yes</label>
<label class="radio-inline"><input id="nofinan" type="radio" name="financiacion" value="0">No</label>
<label class="radio-inline"><input id="nofinan" type="radio" name="financiacion" value="0">No</label>
</div>
<div class="col-sm-8 alert alert-info" style="margin:10px 0px 5px 0px;">
@ -107,8 +107,8 @@
we have submitted funding requests and hope to cover the housing
for a shared room, but we cannot make a guarantee at this time
</em>
</div>
</div>
</div>
</div>
</div>
<!-- Invitation and letter of -->
@ -126,19 +126,19 @@
<label><input id="noinvited" type="radio" name="invited" value="0">No, I am applying(Registration committee will notifiy you if accepted)</label>
</div>
</div>
</div>
</div>
<div class="form-group col-xs-12 col-sm-6">
<label class="control-label" for="invited">
Do you need a letter of invitation?
</label>
<div class="input-container">
<label class="radio-inline"><input id="sifinan" type="radio" name="letterinvited" value="1">Yes</label>
<label class="radio-inline"><input id="nofinan" type="radio" name="letterinvited" value="0">No</label>
</div>
<label class="radio-inline"><input id="nofinan" type="radio" name="letterinvited" value="0">No</label>
</div>
</div>
</div>
<!-- Rooming Preferences -->
<div class="row">
<div class="form-group col-xs-12 col-sm-6">
@ -154,41 +154,48 @@
<label class=" control-label" for="roomate">Name of preferred roommate (if any)</label>
<div class="input-container">
<input id="roomate" name="roomate" class="form-control"
type="text">
</div>
</div>
<input id="roomate" name="roomate" class="form-control"
type="text">
</div>
</div>
</div>
<!--Captcha -->
<div class="row">
<div class="form-group col-xs-12">
<div class="g-recaptcha" data-sitekey="6LesRDsUAAAAAJvyoODvjiza9u75qEGJmbKHEV6s"></div>
<div id="testing" class="g-recaptcha" data-sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"></div>
<!--<div class="g-recaptcha" data-sitekey="6LesRDsUAAAAAJvyoODvjiza9u75qEGJmbKHEV6s"></div>-->
</div>
</div>
<!-- Confirm Button -->
<div class="row">
<div class="form-group col-xs-12 col-sm-8">
<div class="form-group col-xs-12 col-sm-8">
<button type="submit" class="btn-lg btn btn-primary">Register</button>
</div>
</div>
</form>
<div id="statusmsg" class="alert alert-success">
<strong>Success!</strong> Indicates a successful or positive action.
</div>
</form>
<!--{% if flash("submit-register-err") %}-->
<div id="statusmsg" class="alert alert-error">
<strong>Error!</strong>
{% for msg in flash("submit-register-err") %}
<kbd>{{ msg }}.</kdb>
{% endfor %}
</div>
<!-- {% endif %}-->
<!--<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<!--<div class="modal-content">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Revise sus datos cuidadosamente y confirme</h4>
</div>
<div class="modal-body">
<p>Some text in the modal.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">
@ -200,4 +207,4 @@
</div>
</div>-->
{% endblock %}
{% endblock %}