Use link_token when tracking and rendering links

This commit is contained in:
Amine Ben hammou
2019-09-03 12:16:49 +01:00
committed by Jack Kitterhing
parent 042213d5aa
commit 3ea9c99090
17 changed files with 43 additions and 34 deletions

View File

@ -47,7 +47,7 @@ class Links {
}
$data = NewsletterLinks::createUrlDataObject(
$subscriber->id,
$subscriber->email,
$subscriber->getLinkToken(),
$queue->id,
$link_hash->hash,
false

View File

@ -20,6 +20,7 @@ use MailPoet\Util\Security;
* @property string|null $last_subscribed_at
* @property string|null $deleted_at
* @property string|null $source
* @property string|null $link_token
* @property int $count_confirmations
* @property int $wp_user_id
* @property array $segments
@ -102,6 +103,14 @@ class Subscriber extends Model {
return (bool)$this->is_woocommerce_user;
}
function getLinkToken() {
if ($this->link_token === null) {
$this->link_token = self::generateToken($this->email);
$this->save();
}
return $this->link_token;
}
static function getCurrentWPUser() {
$wp_user = WPFunctions::get()->wpGetCurrentUser();
if (empty($wp_user->ID)) {
@ -121,10 +130,10 @@ class Subscriber extends Model {
return false;
}
static function verifyToken($email, $token) {
function verifyToken($token) {
return call_user_func(
'hash_equals',
self::generateToken($email, strlen($token)),
$this->getLinkToken(),
$token
);
}

View File

@ -136,7 +136,7 @@ class Links {
}
$data = self::createUrlDataObject(
$subscriber->id,
$subscriber->email,
$subscriber->getLinkToken(),
$queue_id,
$hash,
$preview
@ -197,11 +197,11 @@ class Links {
}
static function createUrlDataObject(
$subscriber_id, $subscriber_email, $queue_id, $link_hash, $preview
$subscriber_id, $subscriber_link_token, $queue_id, $link_hash, $preview
) {
return [
$subscriber_id,
Subscriber::generateToken($subscriber_email),
$subscriber_link_token,
$queue_id,
$link_hash,
$preview,

View File

@ -17,7 +17,7 @@ class Url {
$preview = false
) {
if ($subscriber instanceof SubscriberModel) {
$subscriber->token = SubscriberModel::generateToken($subscriber->email);
$subscriber->token = $subscriber->getLinkToken();
}
switch ($type) {
case self::TYPE_ARCHIVE:

View File

@ -70,8 +70,7 @@ class Track {
function _validateTrackData($data) {
if (!$data->subscriber || !$data->queue || !$data->newsletter) return false;
$subscriber_token_match =
Subscriber::verifyToken($data->subscriber->email, $data->subscriber_token);
$subscriber_token_match = $data->subscriber->verifyToken($data->subscriber_token);
if (!$subscriber_token_match) {
$this->terminate(403);
}

View File

@ -60,7 +60,7 @@ class ViewInBrowser {
false;
if ($data->subscriber) {
if (empty($data->subscriber_token) ||
!Subscriber::verifyToken($data->subscriber->email, $data->subscriber_token)
!$data->subscriber->verifyToken($data->subscriber_token)
) return false;
} else if (!$data->subscriber && !empty($data->preview)) {
// if this is a preview and subscriber does not exist,

View File

@ -30,12 +30,15 @@ class Manage {
$subscriber_data = $_POST['data'];
$subscriber_data = $this->field_name_obfuscator->deobfuscateFormPayload($subscriber_data);
if (!empty($subscriber_data['email']) && Subscriber::verifyToken($subscriber_data['email'], $token)) {
if (!empty($subscriber_data['email'])) {
$subscriber = Subscriber::where('email', $subscriber_data['email'])->findOne();
if ($subscriber && $subscriber->verifyToken($token)) {
if ($subscriber_data['email'] !== Pages::DEMO_EMAIL) {
$subscriber = Subscriber::createOrUpdate($this->filterOutEmptyMandatoryFields($subscriber_data));
$subscriber->getErrors();
}
}
}
$this->url_helper->redirectBack();
}

View File

@ -103,9 +103,8 @@ class Pages {
return false;
}
return (Subscriber::verifyToken($email, $token)) ?
Subscriber::findOne($email) :
false;
$subscriber = Subscriber::where('email', $email)->findOne();
return ($subscriber && $subscriber->verifyToken($token)) ? $subscriber : false;
}
function confirm() {
@ -283,6 +282,7 @@ class Pages {
'email' => self::DEMO_EMAIL,
'first_name' => 'John',
'last_name' => 'Doe',
'link_token' => Subscriber::generateToken(self::DEMO_EMAIL),
]);
} else if ($this->subscriber !== false) {
$subscriber = $this->subscriber
@ -438,7 +438,7 @@ class Pages {
$subscriber->email .
'" />';
$form_html .= '<input type="hidden" name="token" value="' .
Subscriber::generateToken($subscriber->email) .
$subscriber->getLinkToken() .
'" />';
$form_html .= '<p class="mailpoet_paragraph">';

View File

@ -46,7 +46,7 @@ class Url {
if ($subscriber !== null) {
$data = [
'token' => Subscriber::generateToken($subscriber->email),
'token' => $subscriber->getLinkToken(),
'email' => $subscriber->email,
];
} elseif (is_null($data)) {

View File

@ -99,7 +99,7 @@ class SendingQueueTest extends \MailPoetTest {
private function getTrackedUnsubscribeURL() {
$data = Links::createUrlDataObject(
$this->subscriber->id,
$this->subscriber->email,
$this->subscriber->getLinkToken(),
$this->queue->id,
$this->newsletter_link->hash,
false

View File

@ -678,14 +678,12 @@ class SubscriberTest extends \MailPoetTest {
}
function testItVerifiesSubscriberToken() {
$token = Subscriber::generateToken($this->test_data['email']);
expect(Subscriber::verifyToken($this->test_data['email'], $token))->true();
expect(Subscriber::verifyToken('fake@email.com', $token))->false();
}
function testItVerifiesTokensOfDifferentLengths() {
$token = Subscriber::generateToken($this->test_data['email'], 6);
expect(Subscriber::verifyToken($this->test_data['email'], $token))->true();
$subscriber = Subscriber::createOrUpdate([
'email' => $this->test_data['email'],
]);
$token = $subscriber->getLinkToken();
expect($subscriber->verifyToken($token))->true();
expect($subscriber->verifyToken('faketoken'))->false();
}
function testItBulkDeletesSubscribers() {

View File

@ -126,7 +126,7 @@ class LinksTest extends \MailPoetTest {
];
$url_data_object = Links::createUrlDataObject(
$data['subscriber_id'],
$subscriber_email,
$data['subscriber_token'],
$data['queue_id'],
$data['link_hash'],
$data['preview']

View File

@ -46,7 +46,7 @@ class TrackTest extends \MailPoetTest {
'queue_id' => $queue->id,
'subscriber_id' => $subscriber->id,
'newsletter_id' => $newsletter->id,
'subscriber_token' => Subscriber::generateToken($subscriber->email),
'subscriber_token' => $subscriber->getLinkToken(),
'link_hash' => $link->hash,
'preview' => false,
];

View File

@ -38,7 +38,7 @@ class ViewInBrowserTest extends \MailPoetTest {
'queue_id' => $queue->id,
'subscriber_id' => $subscriber->id,
'newsletter_id' => $newsletter->id,
'subscriber_token' => Subscriber::generateToken($subscriber->email),
'subscriber_token' => $subscriber->getLinkToken(),
'preview' => false,
];
// instantiate class

View File

@ -53,7 +53,7 @@ class ClicksTest extends \MailPoetTest {
'queue' => $queue,
'subscriber' => $subscriber,
'newsletter' => $newsletter,
'subscriber_token' => Subscriber::generateToken($subscriber->email),
'subscriber_token' => $subscriber->getLinkToken(),
'link' => $link,
'preview' => false,
];

View File

@ -35,7 +35,7 @@ class OpensTest extends \MailPoetTest {
'queue' => $queue,
'subscriber' => $subscriber,
'newsletter' => $newsletter,
'subscriber_token' => Subscriber::generateToken($subscriber->email),
'subscriber_token' => $subscriber->getLinkToken(),
'preview' => false,
];
// instantiate class

View File

@ -30,7 +30,7 @@ class PagesTest extends \MailPoetTest {
$this->subscriber->save();
expect($this->subscriber->getErrors())->false();
$this->test_data['email'] = $this->subscriber->email;
$this->test_data['token'] = Subscriber::generateToken($this->subscriber->email);
$this->test_data['token'] = $this->subscriber->getLinkToken();
$this->pages = ContainerWrapper::getInstance()->get(Pages::class);
}