Added subscription limit in order to avoid mass subscriptions

This commit is contained in:
Jonathan Labreuille
2016-11-08 17:29:28 +01:00
parent 1220f47d87
commit 1a6b032943
5 changed files with 68 additions and 1 deletions

View File

@ -73,7 +73,7 @@ class Subscribers extends APIEndpoint {
if(empty($segment_ids)) {
return $this->badRequest(array(
APIError::BAD_REQUEST => __('Please select a list', 'mailpoet')
APIError::BAD_REQUEST => __('Please select a list.', 'mailpoet')
));
}

View File

@ -134,6 +134,9 @@ class Migrator {
'last_name tinytext NOT NULL DEFAULT "",',
'email varchar(150) NOT NULL,',
'status varchar(12) NOT NULL DEFAULT "' . Subscriber::STATUS_UNCONFIRMED . '",',
'ip varchar(32) NULL,',
'confirmed_ip varchar(32) NULL,',
'confirmed_at TIMESTAMP NULL,',
'created_at TIMESTAMP NULL,',
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
'deleted_at TIMESTAMP NULL,',

View File

@ -14,6 +14,8 @@ class Subscriber extends Model {
const STATUS_UNSUBSCRIBED = 'unsubscribed';
const STATUS_UNCONFIRMED = 'unconfirmed';
const SUBSCRIPTION_LIMIT_COOLDOWN = 60;
function __construct() {
parent::__construct();
@ -158,9 +160,27 @@ class Subscriber extends Model {
'signup_confirmation.enabled'
);
// set user ip
$subscriber_data['ip'] = (isset($_SERVER['REMOTE_ADDR']))
? $_SERVER['REMOTE_ADDR']
: null;
// make sure we don't allow too many subscriptions with the same ip address
$subscription_count = Subscriber::where('ip', $subscriber_data['ip'])
->whereRaw(
'TIME_TO_SEC(TIMEDIFF(NOW(), created_at)) < ?',
self::SUBSCRIPTION_LIMIT_COOLDOWN
)
->count();
if($subscription_count > 0) {
throw new \Exception(__('You need to wait before subscribing again.', 'mailpoet'));
}
$subscriber = self::findOne($subscriber_data['email']);
if($subscriber === false) {
// create new subscriber
$subscriber = self::createOrUpdate($subscriber_data);
if($subscriber->getErrors() !== false) {

View File

@ -58,7 +58,12 @@ class Pages {
function confirm() {
if($this->subscriber !== false) {
// update status
$this->subscriber->status = Subscriber::STATUS_SUBSCRIBED;
// set confirmed ip & time
$this->subscriber->confirmed_ip = $_SERVER['REMOTE_ADDR'];
$this->subscriber->setExpr('confirmed_at', 'NOW()');
$this->subscriber->save();
}
}

View File

@ -4,6 +4,7 @@ use \MailPoet\API\Endpoints\Subscribers;
use \MailPoet\API\Response as APIResponse;
use \MailPoet\Models\Subscriber;
use \MailPoet\Models\Segment;
use \MailPoet\Models\Setting;
class SubscribersTest extends MailPoetTest {
function _before() {
@ -26,6 +27,12 @@ class SubscribersTest extends MailPoetTest {
$this->segment_2->id
)
));
// setup mailer
Setting::setValue('sender', array(
'address' => 'sender@mailpoet.com',
'name' => 'Sender'
));
}
function testItCanGetASubscriber() {
@ -354,6 +361,38 @@ class SubscribersTest extends MailPoetTest {
expect($response->errors[0]['message'])->contains('has no method');
}
function testItCanSubscribeAUser() {
// set ip address
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$router = new Subscribers();
// missing segment
$response = $router->subscribe(array(
'email' => 'toto@mailpoet.com'
));
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
expect($response->errors[0]['message'])->equals('Please select a list.');
// proper subscription
$response = $router->subscribe(array(
'email' => 'toto@mailpoet.com',
'segments' => array($this->segment_1->id, $this->segment_2->id)
));
expect($response->status)->equals(APIResponse::STATUS_OK);
try {
$response = $router->subscribe(array(
'email' => 'tata@mailpoet.com',
'segments' => array($this->segment_1->id, $this->segment_2->id)
));
$this->fail('It should not be possible to subscribe a second time so soon');
} catch(\Exception $e) {
expect($e->getMessage())->equals('You need to wait before subscribing again.');
}
}
function _after() {
Segment::deleteMany();
Subscriber::deleteMany();