Added the edit link reminder functionnality

This commit is contained in:
Antonin 2016-04-29 19:39:06 +02:00
parent 8085dd3c3e
commit 391a8f751b
7 changed files with 197 additions and 11 deletions

View File

@ -0,0 +1,98 @@
<?php
/**
* This software is governed by the CeCILL-B license. If a copy of this license
* is not distributed with this file, you can obtain one at
* http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt
*
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
* Authors of Framadate/OpenSondate: Framasoft (https://github.com/framasoft)
*
* =============================
*
* Ce logiciel est régi par la licence CeCILL-B. Si une copie de cette licence
* ne se trouve pas avec ce fichier vous pouvez l'obtenir sur
* http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.txt
*
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
*/
use Framadate\Services\SessionService;
use Framadate\Services\PollService;
use Framadate\Services\MailService;
use Framadate\Services\LogService;
use Framadate\Message;
use Framadate\Utils;
include_once __DIR__ . '/../app/inc/init.php';
$logService = new LogService();
$sessionService = new SessionService();
$mailService = new MailService($config['use_smtp']);
$pollService = new PollService($connect, $logService);
$result = false;
$message = null;
$poll = null;
$poll_id = null;
$email = null;
if (!empty($_POST['poll'])) {
$poll_id = filter_input(INPUT_POST, 'poll', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
$poll = $pollService->findById($poll_id);
}
$token = $sessionService->get("Common", SESSION_EDIT_LINK_TOKEN);
$token_form_value = empty($_POST['token']) ? null : $_POST['token'];
$editedVoteUniqueId = filter_input(INPUT_POST, 'editedVoteUniqueId', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
if (is_null($poll) || $config['use_smtp'] == false || is_null($token) || is_null($token_form_value)
|| !$token->check($token_form_value) || is_null($editedVoteUniqueId)) {
$message = new Message('error', __('Error', 'Something is going wrong...'));
}
if (is_null($message)) {
$email = $mailService->isValidEmail($_POST['email']);
if (is_null($email)) {
$message = new Message('error', __('EditLink', 'The email address is not correct.'));
}
}
if (is_null($message)) {
$time = $sessionService->get("Common", SESSION_EDIT_LINK_TIME);
if (!empty($time)) {
$remainingTime = TIME_EDIT_LINK_EMAIL - (time() - $time);
if ($remainingTime > 0) {
$message = new Message('error', sprintf(__('EditLink', 'Please wait %d seconds before we can send an email to you then try again.'), $remainingTime));
}
}
}
if (is_null($message)) {
$url = Utils::getUrlSondage($poll_id, false, $editedVoteUniqueId);
$smarty->assign('poll', $poll);
$smarty->assign('poll_id', $poll_id);
$smarty->assign('editedVoteUniqueId', $editedVoteUniqueId);
$body = $smarty->fetch('mail/remember_edit_link.tpl');
$subject = '[' . NOMAPPLICATION . ']['.__('EditLink', 'REMINDER').'] '.sprintf(__('EditLink', 'Edit link for poll "%s"'), $poll->title);
//$mailService->send($email, $subject, $body);
$sessionService->remove("Common", SESSION_EDIT_LINK_TOKEN);
$sessionService->set("Common", SESSION_EDIT_LINK_TIME, time());
$message = new Message('success', __('EditLink', 'Your reminder has been successfully sent!'));
$result = true;
}
error_reporting(E_ALL & ~E_NOTICE);
$smarty->error_reporting = E_ALL & ~E_NOTICE;
$response = array('result' => $result, 'message' => $message, '$email'=> $email, '$subject'=>$subject, '$body'=>$body);
echo json_encode($response);

View File

@ -77,6 +77,9 @@ const PURGE_DELAY = 60;
// Max slots per poll // Max slots per poll
const MAX_SLOTS_PER_POLL = 366; const MAX_SLOTS_PER_POLL = 366;
// Number of seconds before we allow to resend an "Remember Edit Link" email.
const TIME_EDIT_LINK_EMAIL = 60;
// Config // Config
$config = [ $config = [
/* general config */ /* general config */

View File

@ -30,5 +30,9 @@ const EDITABLE_CHOICE_REGEX = '/^[0-2]$/';
const BASE64_REGEX = '/^[A-Za-z0-9]+$/'; const BASE64_REGEX = '/^[A-Za-z0-9]+$/';
const MD5_REGEX = '/^[A-Fa-f0-9]{32}$/'; const MD5_REGEX = '/^[A-Fa-f0-9]{32}$/';
// Session constants
const SESSION_EDIT_LINK_TOKEN = 'EditLinkToken';
const SESSION_EDIT_LINK_TIME = "EditLinkMail";
// CSRF (300s = 5min) // CSRF (300s = 5min)
const TOKEN_TIME = 300; const TOKEN_TIME = 300;

View File

@ -28,6 +28,7 @@ use Framadate\Services\SessionService;
use Framadate\Message; use Framadate\Message;
use Framadate\Utils; use Framadate\Utils;
use Framadate\Editable; use Framadate\Editable;
use Framadate\Security\Token;
include_once __DIR__ . '/app/inc/init.php'; include_once __DIR__ . '/app/inc/init.php';
@ -147,6 +148,15 @@ if ($accessGranted) {
$urlEditVote, $urlEditVote,
__('Poll results', 'Edit the line:').' '.$name, __('Poll results', 'Edit the line:').' '.$name,
'glyphicon-pencil'); 'glyphicon-pencil');
if ($config['use_smtp']) {
$token = new Token();
$sessionService->set("Common", SESSION_EDIT_LINK_TOKEN, $token);
$smarty->assign('editedVoteUniqueId', $editedVoteUniqueId);
$smarty->assign('token', $token->getValue());
$smarty->assign('poll_id', $poll_id);
$message->includeTemplate = $smarty->fetch('part/form_remember_edit_link.tpl');
$smarty->clearAssign('token');
}
} else { } else {
$message = new Message('success', __('studs', 'Update vote succeeded')); $message = new Message('success', __('studs', 'Update vote succeeded'));
} }
@ -179,7 +189,21 @@ if ($accessGranted) {
$editedVoteUniqueId = $result->uniqId; $editedVoteUniqueId = $result->uniqId;
$sessionService->set(USER_REMEMBER_VOTES_KEY, $poll_id, $editedVoteUniqueId); $sessionService->set(USER_REMEMBER_VOTES_KEY, $poll_id, $editedVoteUniqueId);
$urlEditVote = Utils::getUrlSondage($poll_id, false, $editedVoteUniqueId); $urlEditVote = Utils::getUrlSondage($poll_id, false, $editedVoteUniqueId);
$message = new Message('success', __('studs', 'Your vote has been registered successfully, but be careful: regarding this poll options, you need to keep this personal link to edit your own vote:'), $urlEditVote); $message = new Message(
'success',
__('studs', 'Your vote has been registered successfully, but be careful: regarding this poll options, you need to keep this personal link to edit your own vote:'),
$urlEditVote,
__('Poll results', 'Edit the line:').' '.$name,
'glyphicon-pencil');
if ($config['use_smtp']) {
$token = new Token();
$sessionService->set("Common", SESSION_EDIT_LINK_TOKEN, $token);
$smarty->assign('editedVoteUniqueId', $editedVoteUniqueId);
$smarty->assign('token', $token->getValue());
$smarty->assign('poll_id', $poll_id);
$message->includeTemplate = $smarty->fetch('part/form_remember_edit_link.tpl');
$smarty->clearAssign('token');
}
} else { } else {
$message = new Message('success', __('studs', 'Adding the vote succeeded')); $message = new Message('success', __('studs', 'Adding the vote succeeded'));
} }

View File

@ -1,9 +1,5 @@
<h1>{__('FindPolls', 'Here are your polls')}</h1> <h1>{$poll->title|html|string_format:__('EditLink', 'Edit link for poll "%s"')}</h1>
<ul> <p>
{foreach $polls as $poll} {__('EditLink', 'Here is the link for editing your vote:')}
<li> <a href="{poll_url id=$poll->admin_id vote_id=$editedVoteUniqueId}">{$poll->title|html}</a>
<a href="{poll_url id=$poll->admin_id admin=true}">{$poll->title|html}</a> </p>
({__('Generic', 'Creation date:')} {$poll->creation_date|date_format:$date_format['txt_full']})
</li>
{/foreach}
</ul>

View File

@ -0,0 +1,57 @@
<div class="well">
<form action="action/send_edit_link_by_email_action.php" method="POST" class="form-inline" id="send_edit_link_form">
<p>{__('EditLink', 'If you don't want to lose your personalized link, we can send it to your email.')}</p>
<input type="hidden" name="token" value="{$token}"/>
<input type="hidden" name="poll" value="{$poll_id}"/>
<input type="hidden" name="editedVoteUniqueId" value="{$editedVoteUniqueId}"/>
<div class="form-group">
<label for="email" class="control-label">{__('PollInfo', 'Email')}</label>
<input type="email" name="email" id="email" class="form-control" />
<input type="submit" id="send_edit_link_submit" value="{__('EditLink', 'Send')}" class="btn btn-success">
</div>
</form>
<div id="send_edit_link_alert"></div>
</div>
<script>
$(document).ready(function () {
var form = $('#send_edit_link_form');
form.submit(function(event) {
event.preventDefault();
if ($('#email').val()) {
//$('#send_edit_link_submit').attr("disabled", "disabled");
$.ajax({
type: 'POST',
url: form.attr('action'),
data: form.serialize(),
dataType: 'json',
success: function(data)
{
var newMessage;
if (data.result) {
$('#send_edit_link_form').remove();
newMessage = $('#genericUnclosableSuccessTemplate').clone();
} else {
newMessage = $('#genericErrorTemplate').clone();
}
newMessage
.find('.contents')
.text(data.message.message);
newMessage.removeClass('hidden');
$('#send_edit_link_alert')
.empty()
.append(newMessage);
},
complete: function() {
$('#add_comment').removeAttr("disabled");
}
});
}
return false;
});
});
</script>

View File

@ -16,6 +16,7 @@
<div id="message-container"> <div id="message-container">
{if !empty($message)} {if !empty($message)}
<div class="alert alert-dismissible alert-{$message->type|html} hidden-print" role="alert"> <div class="alert alert-dismissible alert-{$message->type|html} hidden-print" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="{__('Generic', 'CLose')}"><span aria-hidden="true">&times;</span></button>
{$message->message|html} {$message->message|html}
{if $message->link != null} {if $message->link != null}
<div class="input-group input-group-sm"> <div class="input-group input-group-sm">
@ -26,13 +27,16 @@
</span> </span>
<input type="text" aria-hidden="true" value="{$message->link}" class="form-control" readonly="readonly" > <input type="text" aria-hidden="true" value="{$message->link}" class="form-control" readonly="readonly" >
</div> </div>
{if $message->includeTemplate != null}
{$message->includeTemplate}
{/if}
{/if} {/if}
<button type="button" class="close" data-dismiss="alert" aria-label="{__('Generic', 'CLose')}"><span aria-hidden="true">&times;</span></button>
</div> </div>
{/if} {/if}
</div> </div>
<div id="nameErrorMessage" class="hidden alert alert-dismissible alert-danger hidden-print" role="alert">{__('Error', 'The name is invalid.')}<button type="button" class="close" data-dismiss="alert" aria-label="{__('Generic', 'CLose')}"><span aria-hidden="true">&times;</span></button></div> <div id="nameErrorMessage" class="hidden alert alert-dismissible alert-danger hidden-print" role="alert">{__('Error', 'The name is invalid.')}<button type="button" class="close" data-dismiss="alert" aria-label="{__('Generic', 'CLose')}"><span aria-hidden="true">&times;</span></button></div>
<div id="genericErrorTemplate" class="hidden alert alert-dismissible alert-danger hidden-print" role="alert"><span class="contents"></span><button type="button" class="close" data-dismiss="alert" aria-label="{__('Generic', 'CLose')}"><span aria-hidden="true">&times;</span></button></div> <div id="genericErrorTemplate" class="hidden alert alert-dismissible alert-danger hidden-print" role="alert"><span class="contents"></span><button type="button" class="close" data-dismiss="alert" aria-label="{__('Generic', 'CLose')}"><span aria-hidden="true">&times;</span></button></div>
<div id="genericUnclosableSuccessTemplate" class="hidden alert alert-success hidden-print" role="alert"><span class="contents"></span></div>
{if !$accessGranted && !$resultPubliclyVisible} {if !$accessGranted && !$resultPubliclyVisible}