Password options are used with poll creation.

- Just found that the "hidden" parameter wasn't...
This commit is contained in:
Antonin 2015-04-09 17:53:00 +02:00
parent cddbf3cb43
commit 161b6b14c0
11 changed files with 177 additions and 23 deletions

View File

@ -51,6 +51,24 @@ class Form
*/ */
public $hidden; public $hidden;
/**
* If true, a password will be needed to access the poll
* @var boolean
*/
public $use_password;
/**
* The password needed to access the poll, if $use_password is set to true
* @var string
*/
public $password;
/**
* If true, the polls results will be also visible for those without password
* @var boolean
*/
public $results_publicly_visible;
/** /**
* List of available choices * List of available choices
*/ */

View File

@ -11,12 +11,12 @@ class PollRepository extends AbstractRepository {
parent::__construct($connect); parent::__construct($connect);
} }
public function insertPoll($poll_id, $admin_poll_id, $form) { public function insertPoll($poll_id, $admin_poll_id, $form, $password_hash, $results_publicly_visible) {
$sql = 'INSERT INTO `' . Utils::table('poll') . '` $sql = 'INSERT INTO `' . Utils::table('poll') . '`
(id, admin_id, title, description, admin_name, admin_mail, end_date, format, editable, receiveNewVotes, receiveNewComments) (id, admin_id, title, description, admin_name, admin_mail, end_date, format, editable, receiveNewVotes, receiveNewComments, hidden, password_hash, results_publicly_visible)
VALUES (?,?,?,?,?,?,FROM_UNIXTIME(?),?,?,?,?)'; VALUES (?,?,?,?,?,?,FROM_UNIXTIME(?),?,?,?,?,?,?,?)';
$prepared = $this->prepare($sql); $prepared = $this->prepare($sql);
$prepared->execute(array($poll_id, $admin_poll_id, $form->title, $form->description, $form->admin_name, $form->admin_mail, $form->end_date, $form->format, $form->editable, $form->receiveNewVotes, $form->receiveNewComments)); $prepared->execute(array($poll_id, $admin_poll_id, $form->title, $form->description, $form->admin_name, $form->admin_mail, $form->end_date, $form->format, $form->editable, $form->receiveNewVotes, $form->receiveNewComments, $form->hidden, $password_hash, $results_publicly_visible));
} }
function findById($poll_id) { function findById($poll_id) {

View File

@ -15,7 +15,7 @@ class PasswordHasher {
/** /**
* Hash a password * Hash a password
* *
* @param $password the password to hash. * @param string $password the password to hash.
* @return false|string the hashed password, or false on failure. The used algorithm, cost and salt are returned as part of the hash. * @return false|string the hashed password, or false on failure. The used algorithm, cost and salt are returned as part of the hash.
*/ */
public static function hash($password) { public static function hash($password) {
@ -25,8 +25,8 @@ class PasswordHasher {
/** /**
* Verify a password with a hash * Verify a password with a hash
* *
* @param $password the password to verify * @param string $password the password to verify
* @param $hash the hash to compare. * @param string $hash the hash to compare.
* @return bool * @return bool
*/ */
public static function verify($password, $hash) { public static function verify($password, $hash) {

View File

@ -20,8 +20,10 @@ namespace Framadate\Services;
use Framadate\Form; use Framadate\Form;
use Framadate\FramaDB; use Framadate\FramaDB;
use Framadate\Repositories\RepositoryFactory; use Framadate\Utils;
use Framadate\Security\Token; use Framadate\Security\Token;
use Framadate\Security\PasswordHasher;
use Framadate\Repositories\RepositoryFactory;
class PollService { class PollService {
@ -118,9 +120,18 @@ class PollService {
} while ($this->pollRepository->existsById($poll_id)); } while ($this->pollRepository->existsById($poll_id));
$admin_poll_id = $poll_id . $this->random(8); $admin_poll_id = $poll_id . $this->random(8);
// Password hash, if needed
if ($form->use_password) {
$password_hash = PasswordHasher::hash($form->password);
$results_publicly_visible = $form->results_publicly_visible;
} else {
$password_hash = null;
$results_publicly_visible = null;
}
// Insert poll + slots // Insert poll + slots
$this->pollRepository->beginTransaction(); $this->pollRepository->beginTransaction();
$this->pollRepository->insertPoll($poll_id, $admin_poll_id, $form); $this->pollRepository->insertPoll($poll_id, $admin_poll_id, $form, $password_hash, $results_publicly_visible);
$this->slotRepository->insertSlots($poll_id, $form->getChoices()); $this->slotRepository->insertSlots($poll_id, $form->getChoices());
$this->pollRepository->commit(); $this->pollRepository->commit();

View File

@ -19,6 +19,7 @@
use Framadate\Form; use Framadate\Form;
use Framadate\Services\InputService; use Framadate\Services\InputService;
use Framadate\Editable;
use Framadate\Utils; use Framadate\Utils;
include_once __DIR__ . '/app/inc/init.php'; include_once __DIR__ . '/app/inc/init.php';
@ -60,12 +61,18 @@ if ($goToStep2) {
$receiveNewVotes = isset($_POST['receiveNewVotes']) ? $inputService->filterBoolean($_POST['receiveNewVotes']) : false; $receiveNewVotes = isset($_POST['receiveNewVotes']) ? $inputService->filterBoolean($_POST['receiveNewVotes']) : false;
$receiveNewComments = isset($_POST['receiveNewComments']) ? $inputService->filterBoolean($_POST['receiveNewComments']) : false; $receiveNewComments = isset($_POST['receiveNewComments']) ? $inputService->filterBoolean($_POST['receiveNewComments']) : false;
$hidden = isset($_POST['hidden']) ? $inputService->filterBoolean($_POST['hidden']) : false; $hidden = isset($_POST['hidden']) ? $inputService->filterBoolean($_POST['hidden']) : false;
$use_password = filter_input(INPUT_POST, 'use_password', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_REGEX]]);
$password = isset($_POST['password'])?$_POST['password']:null;
$password_repeat = isset($_POST['password_repeat'])?$_POST['password_repeat']:null;
$results_publicly_visible = filter_input(INPUT_POST, 'results_publicly_visible', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_REGEX]]);
// On initialise également les autres variables // On initialise également les autres variables
$error_on_mail = false; $error_on_mail = false;
$error_on_title = false; $error_on_title = false;
$error_on_name = false; $error_on_name = false;
$error_on_description = false; $error_on_description = false;
$error_on_password = false;
$error_on_password_repeat = false;
$_SESSION['form']->title = $title; $_SESSION['form']->title = $title;
$_SESSION['form']->admin_name = $name; $_SESSION['form']->admin_name = $name;
@ -75,6 +82,10 @@ if ($goToStep2) {
$_SESSION['form']->receiveNewVotes = $receiveNewVotes; $_SESSION['form']->receiveNewVotes = $receiveNewVotes;
$_SESSION['form']->receiveNewComments = $receiveNewComments; $_SESSION['form']->receiveNewComments = $receiveNewComments;
$_SESSION['form']->hidden = $hidden; $_SESSION['form']->hidden = $hidden;
$_SESSION['form']->use_password = ($use_password !== null);
$_SESSION['form']->password = $password;
$_SESSION['form']->results_publicly_visible = ($results_publicly_visible !== null);
if ($config['use_smtp'] == true) { if ($config['use_smtp'] == true) {
if (empty($mail)) { if (empty($mail)) {
@ -101,7 +112,16 @@ if ($goToStep2) {
$email_OK = true; $email_OK = true;
} }
if ($title && $name && $email_OK && !$error_on_title && !$error_on_description && !$error_on_name) { if ($use_password) {
if (empty($password)) {
$error_on_password = true;
} else if ($password != $password_repeat) {
$error_on_password_repeat = true;
}
}
if ($title && $name && $email_OK && !$error_on_title && !$error_on_description && !$error_on_name
&& !$error_on_password && !$error_on_password_repeat) {
if ($goToStep2 == 'date') { if ($goToStep2 == 'date') {
header('Location:create_date_poll.php'); header('Location:create_date_poll.php');
@ -143,6 +163,16 @@ $errors = array(
'msg' => '', 'msg' => '',
'aria' => '', 'aria' => '',
'class' => '' 'class' => ''
),
'password' => array(
'msg' => '',
'aria' => '',
'class' => ''
),
'password_repeat' => array(
'msg' => '',
'aria' => '',
'class' => ''
) )
); );
@ -182,6 +212,17 @@ if (!empty($_POST[GO_TO_STEP_2])) {
$errors['email']['class'] = ' has-error'; $errors['email']['class'] = ' has-error';
$errors['email']['msg'] = __('Error', 'The address is not correct! You should enter a valid email address (like r.stallman@outlock.com) in order to receive the link to your poll.'); $errors['email']['msg'] = __('Error', 'The address is not correct! You should enter a valid email address (like r.stallman@outlock.com) in order to receive the link to your poll.');
} }
if ($error_on_password) {
$errors['password']['aria'] = 'aria-describeby="poll_password_error" ';
$errors['password']['class'] = ' has-error';
$errors['password']['msg'] = __('Error', 'Password is empty');
}
if ($error_on_password_repeat) {
$errors['password_repeat']['aria'] = 'aria-describeby="poll_password_repeat_error" ';
$errors['password_repeat']['class'] = ' has-error';
$errors['password_repeat']['msg'] = __('Error', 'Passwords do not match');
}
} }
$useRemoteUser = USE_REMOTE_USER && isset($_SERVER['REMOTE_USER']); $useRemoteUser = USE_REMOTE_USER && isset($_SERVER['REMOTE_USER']);
@ -201,6 +242,9 @@ $smarty->assign('poll_editable', Utils::fromPostOrDefault('editable', $_SESSION[
$smarty->assign('poll_receiveNewVotes', Utils::fromPostOrDefault('receiveNewVotes', $_SESSION['form']->receiveNewVotes)); $smarty->assign('poll_receiveNewVotes', Utils::fromPostOrDefault('receiveNewVotes', $_SESSION['form']->receiveNewVotes));
$smarty->assign('poll_receiveNewComments', Utils::fromPostOrDefault('receiveNewComments', $_SESSION['form']->receiveNewComments)); $smarty->assign('poll_receiveNewComments', Utils::fromPostOrDefault('receiveNewComments', $_SESSION['form']->receiveNewComments));
$smarty->assign('poll_hidden', Utils::fromPostOrDefault('hidden', $_SESSION['form']->hidden)); $smarty->assign('poll_hidden', Utils::fromPostOrDefault('hidden', $_SESSION['form']->hidden));
$smarty->assign('poll_use_password', Utils::fromPostOrDefault('use_password', $_SESSION['form']->use_password));
$smarty->assign('poll_results_publicly_visible', Utils::fromPostOrDefault('results_publicly_visible', $_SESSION['form']->results_publicly_visible));
$smarty->assign('poll_password', Utils::fromPostOrDefault('password', $_SESSION['form']->password));
$smarty->assign('form', $_SESSION['form']); $smarty->assign('form', $_SESSION['form']);
$smarty->display('create_poll.tpl'); $smarty->display('create_poll.tpl');

View File

@ -18,6 +18,9 @@
$(document).ready(function () { $(document).ready(function () {
/**
* Error check when submitting form
*/
$("#formulaire").submit(function (event) { $("#formulaire").submit(function (event) {
var isHidden = $("#hidden").prop('checked'); var isHidden = $("#hidden").prop('checked');
var isOptionAllUserCanModifyEverything = $("#editableByAll").is(":checked"); var isOptionAllUserCanModifyEverything = $("#editableByAll").is(":checked");
@ -30,6 +33,18 @@ $(document).ready(function () {
} }
}); });
/**
* Hide/Show password options
*/
var usePassword = $("#use_password");
usePassword.change(function(){
if (usePassword.prop("checked")) {
$("#password_options").removeClass("hidden");
} else {
$("#password_options").addClass("hidden");
}
});
// Check cookies are enabled too // Check cookies are enabled too
var cookieEnabled = function () { var cookieEnabled = function () {
var cookieEnabled = navigator.cookieEnabled; var cookieEnabled = navigator.cookieEnabled;

View File

@ -211,6 +211,10 @@
"To receive an email for each new vote": "Bei jeder neuen Wertung eine E-Mail erhalten", "To receive an email for each new vote": "Bei jeder neuen Wertung eine E-Mail erhalten",
"To receive an email for each new comment": "Bei jedem neuen Kommentar eine E-Mail erhalten", "To receive an email for each new comment": "Bei jedem neuen Kommentar eine E-Mail erhalten",
"Only the poll maker can see the poll's results": "Einzig der Autor der Abstimmung kann die Ergebnisse einsehen.", "Only the poll maker can see the poll's results": "Einzig der Autor der Abstimmung kann die Ergebnisse einsehen.",
"Use a password to restrict access.": "DE_Utiliser un mot de passe pour restreindre l'accès au sondage.",
"The results are publicly visible.": "DE_Les résultats sont visibles sans mot de passe.",
"Poll password": "DE_Mot de passe",
"Confirm password": "DE_Confirmer votre mot de passe.",
"Go to step 2": "Weiter zum 2. Schritt" "Go to step 2": "Weiter zum 2. Schritt"
}, },
"Step 2": { "Step 2": {
@ -338,6 +342,9 @@
"You can't create a poll with hidden results with the following edition option:": "Sie können mit der folgenden Editier-Option keine Umfrage mit versteckten Ergebnissen erzeugen:", "You can't create a poll with hidden results with the following edition option:": "Sie können mit der folgenden Editier-Option keine Umfrage mit versteckten Ergebnissen erzeugen:",
"Failed to delete column": "Löschen der Spalte fehlgeschlagen", "Failed to delete column": "Löschen der Spalte fehlgeschlagen",
"MISSING_VALUES": "Fehlende Werte", "MISSING_VALUES": "Fehlende Werte",
"CANT_CONNECT_TO_DATABASE": "Kann nicht mit der Datenbank verbinden" "CANT_CONNECT_TO_DATABASE": "Kann nicht mit der Datenbank verbinden",
"Password is empty": "DE_Le mot de passe est vide.",
"Passwords do not match": "DE_Les mot de passes ne correspondent pas."
} }
} }

View File

@ -211,6 +211,10 @@
"To receive an email for each new vote": "Receive an email for each new vote", "To receive an email for each new vote": "Receive an email for each new vote",
"To receive an email for each new comment": "Receive an email for each new comment", "To receive an email for each new comment": "Receive an email for each new comment",
"Only the poll maker can see the poll's results": "Only the poll maker can see the poll results", "Only the poll maker can see the poll's results": "Only the poll maker can see the poll results",
"Use a password to restrict access.": "Use a password to restrict access.",
"The results are publicly visible.": "The results are publicly visible.",
"Poll password": "Password",
"Confirm password": "Confirmer votre mot de passe.",
"Go to step 2": "Go to step 2" "Go to step 2": "Go to step 2"
}, },
"Step 2": { "Step 2": {
@ -272,9 +276,9 @@
"Expiration date": "Expiry date", "Expiration date": "Expiry date",
"Votes": "Votes", "Votes": "Votes",
"Actions": "Actions", "Actions": "Actions",
"See the poll": "Go to poll", "See the poll": "See the poll",
"Change the poll": "Change poll", "Change the poll": "Change the poll",
"Deleted the poll": "Delete the poll", "Deleted the poll": "Deleted the poll",
"Summary": "Summary", "Summary": "Summary",
"Success": "Success", "Success": "Success",
"Fail": "Fail", "Fail": "Fail",
@ -338,6 +342,8 @@
"You can't create a poll with hidden results with the following edition option:": "You can't create a poll with hidden results with the following option: ", "You can't create a poll with hidden results with the following edition option:": "You can't create a poll with hidden results with the following option: ",
"Failed to delete column": "Failed to delete column", "Failed to delete column": "Failed to delete column",
"MISSING_VALUES": "Missing values", "MISSING_VALUES": "Missing values",
"CANT_CONNECT_TO_DATABASE": "Unable to connect to database" "CANT_CONNECT_TO_DATABASE": "Unable to connect to database",
"Password is empty": "Password is empty.",
"Passwords do not match": "Passwords do not match."
} }
} }

View File

@ -211,6 +211,10 @@
"To receive an email for each new vote": "Usted quiere recibir un correo electónico cada vez que alguien participe a la encuesta", "To receive an email for each new vote": "Usted quiere recibir un correo electónico cada vez que alguien participe a la encuesta",
"To receive an email for each new comment": "ES_Recevoir un courriel à chaque commentaire", "To receive an email for each new comment": "ES_Recevoir un courriel à chaque commentaire",
"Only the poll maker can see the poll's results": "ES_Seul le créateur du sondage peut voir les résultats", "Only the poll maker can see the poll's results": "ES_Seul le créateur du sondage peut voir les résultats",
"Use a password to restrict access.": "ES_Utiliser un mot de passe pour restreindre l'accès au sondage.",
"The results are publicly visible.": "ES_Les résultats sont visibles sans mot de passe.",
"Poll password": "ES_Mot de passe",
"Confirm password": "ES_Confirmer votre mot de passe.",
"Go to step 2": "ES_Aller à l'étape 2" "Go to step 2": "ES_Aller à l'étape 2"
}, },
"Step 2": { "Step 2": {
@ -338,6 +342,9 @@
"You can't create a poll with hidden results with the following edition option:": "ES_Vous ne pouvez pas créer de sondage avec résulats cachés avec les options d'éditions suivantes : ", "You can't create a poll with hidden results with the following edition option:": "ES_Vous ne pouvez pas créer de sondage avec résulats cachés avec les options d'éditions suivantes : ",
"Failed to delete column": "Error al eliminar la columna", "Failed to delete column": "Error al eliminar la columna",
"MISSING_VALUES": "Los valores perdidos", "MISSING_VALUES": "Los valores perdidos",
"CANT_CONNECT_TO_DATABASE": "No se puede conectar a la base de datos" "CANT_CONNECT_TO_DATABASE": "No se puede conectar a la base de datos",
"Password is empty": "ES_Le mot de passe est vide.",
"Passwords do not match": "ES_Les mot de passes ne correspondent pas."
} }
} }

View File

@ -211,6 +211,10 @@
"To receive an email for each new vote": "Recevoir un courriel à chaque participation d'un sondé", "To receive an email for each new vote": "Recevoir un courriel à chaque participation d'un sondé",
"To receive an email for each new comment": "Recevoir un courriel à chaque commentaire", "To receive an email for each new comment": "Recevoir un courriel à chaque commentaire",
"Only the poll maker can see the poll's results": "Seul le créateur du sondage peut voir les résultats", "Only the poll maker can see the poll's results": "Seul le créateur du sondage peut voir les résultats",
"Use a password to restrict access.": "Utiliser un mot de passe pour restreindre l'accès au sondage.",
"The results are publicly visible.": "Les résultats sont visibles sans mot de passe.",
"Poll password": "Mot de passe",
"Confirm password": "Confirmer votre mot de passe.",
"Go to step 2": "Aller à l'étape 2" "Go to step 2": "Aller à l'étape 2"
}, },
"Step 2": { "Step 2": {
@ -263,7 +267,6 @@
"Migration": "Migration", "Migration": "Migration",
"Purge": "Purge", "Purge": "Purge",
"Logs": "Historique", "Logs": "Historique",
"Installation": "Installation",
"Poll ID": "ID sondage", "Poll ID": "ID sondage",
"Format": "Format", "Format": "Format",
"Title": "Titre", "Title": "Titre",

View File

@ -49,7 +49,7 @@
</div> </div>
{/if} {/if}
<div class="form-group '.$errors['name']['class'].'"> <div class="form-group {$errors['name']['class']}">
<label for="yourname" class="col-sm-4 control-label">{__('Generic', 'Your name')} *</label> <label for="yourname" class="col-sm-4 control-label">{__('Generic', 'Your name')} *</label>
<div class="col-sm-8"> <div class="col-sm-8">
@ -69,7 +69,7 @@
{/if} {/if}
{if $use_smtp} {if $use_smtp}
<div class="form-group '.$errors['email']['class'].'"> <div class="form-group {$errors['email']['class']}">
<label for="email" class="col-sm-4 control-label"> <label for="email" class="col-sm-4 control-label">
{__('Generic', 'Your email address')} *<br/> {__('Generic', 'Your email address')} *<br/>
<span class="small">{__('Generic', '(in the format name@mail.com)')}</span> <span class="small">{__('Generic', '(in the format name@mail.com)')}</span>
@ -136,7 +136,7 @@
</div> </div>
</div> </div>
</div> </div>
{/if} {/if}
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-4 col-sm-8"> <div class="col-sm-offset-4 col-sm-8">
@ -144,18 +144,61 @@
<label> <label>
<input type="checkbox" name="hidden" {if $poll_hidden}checked{/if} <input type="checkbox" name="hidden" {if $poll_hidden}checked{/if}
id="hidden"> id="hidden">
{__('Step 1', 'Only the poll maker can see the poll\'s results')} {__('Step 1', "Only the poll maker can see the poll's results")}
</label> </label>
</div> </div>
<div id="hiddenWithBadEditionModeError" class="alert alert-danger hidden"> <div id="hiddenWithBadEditionModeError" class="alert alert-danger hidden">
<p> <p>
{__('Error', 'You can\'t create a poll with hidden results with the following edition option:')}"{__('Step 1', 'All voters can modify any vote')}" {__('Error', "You can't create a poll with hidden results with the following edition option:")}"{__('Step 1', 'All voters can modify any vote')}"
</p> </p>
</div> </div>
</div> </div>
</div> </div>
<div class="form-group">
<div class="col-sm-offset-4 col-sm-8">
<div class="checkbox">
<label>
<input type="checkbox" name="use_password" {if $poll_use_password}checked{/if}
id="use_password">
{__('Step 1', "Use a password to restrict access.")}
</label>
</div>
</div>
<div id="password_options"{if !$poll_use_password} class="hidden"{/if}>
<label for="poll_password" class="col-sm-4 control-label">{__('Step 1', 'Poll password')}</label>
<div class="col-sm-8">
<input id="poll_password" type="password" name="password" class="form-control" {$errors['password']['aria']}/>
</div>
{if !empty($errors['password']['msg'])}
<div class="alert alert-danger">
<p id="poll_password_error">
{$errors['password']['msg']}
</p>
</div>
{/if}
<label for="poll_password_repeat" class="col-sm-4 control-label">{__('Step 1', 'Confirm password')}</label>
<div class="col-sm-8">
<input id="poll_password_repeat" type="password" name="password_repeat" class="form-control" {$errors['password_repeat']['aria']}/>
</div>
{if !empty($errors['password_repeat']['msg'])}
<div class="alert alert-danger">
<p id="poll_password_repeat_error">
{$errors['password_repeat']['msg']}
</p>
</div>
{/if}
<div class="col-sm-offset-4 col-sm-8">
<div class="checkbox">
<label>
<input type="checkbox" name="results_publicly_visible"
{if $poll_results_publicly_visible}checked{/if} id="results_publicly_visible"/>
{__('Step 1', "The results are publicly visible.")}
</label>
</div>
</div>
</div>
</div>