Skip to content

Commit

Permalink
Adding Tests, updating README, and fixing formatting for readability.
Browse files Browse the repository at this point in the history
  • Loading branch information
chronon committed Mar 10, 2012
1 parent 72dc9c5 commit 6ab7a2c
Show file tree
Hide file tree
Showing 7 changed files with 272 additions and 18 deletions.
23 changes: 19 additions & 4 deletions Controller/Component/AttemptComponent.php
Expand Up @@ -10,6 +10,7 @@
* @package app
* @subpackage app.controllers.components
**/

class AttemptComponent extends Component {

// Called after the Controller::beforeFilter() and before the controller action
Expand All @@ -19,19 +20,33 @@ public function startup($controller) {
}

public function count($action) {
return $this->Attempt->count($this->Controller->request->clientIp(), $action);
return $this->Attempt->count(
$this->Controller->request->clientIp(),
$action
);
}

public function limit($action, $limit = 5) {
return $this->Attempt->limit($this->Controller->request->clientIp(), $action, $limit);
return $this->Attempt->limit(
$this->Controller->request->clientIp(),
$action,
$limit
);
}

public function fail($action, $duration = '+10 minutes') {
return $this->Attempt->fail($this->Controller->request->clientIp(), $action, $duration);
return $this->Attempt->fail(
$this->Controller->request->clientIp(),
$action,
$duration
);
}

public function reset($action) {
return $this->Attempt->reset($this->Controller->request->clientIp(), $action);
return $this->Attempt->reset(
$this->Controller->request->clientIp(),
$action
);
}

public function cleanup() {
Expand Down
27 changes: 15 additions & 12 deletions Model/Attempt.php
Expand Up @@ -18,24 +18,27 @@ public function limit($ip, $action, $limit) {
}

public function fail($ip, $action, $duration) {
$this->create(array(
'ip' => $ip,
'action' => $action,
'expires' => date('Y-m-d H:i:s', strtotime($duration))
));
$this->create(
array(
'ip' => $ip,
'action' => $action,
'expires' => date('Y-m-d H:i:s', strtotime($duration))
)
);
return $this->save();
}

public function reset($ip, $action) {
return $this->deleteAll(array(
'ip' => $ip,
'action' => $action
),false, false);
return $this->deleteAll(
array('ip' => $ip, 'action' => $action),
false
);
}

public function cleanup() {
return $this->deleteAll(array(
'expires <' => date('Y-m-d H:i:s')
), false, false);
return $this->deleteAll(
array('expires <' => date('Y-m-d H:i:s')),
false
);
}
}
3 changes: 1 addition & 2 deletions README.markdown
@@ -1,8 +1,7 @@
Attempt Component
=================

A simple component to protect sensitive actions from brute force attacks.

A CakePHP 2.0 or 2.1 plugin that helps to protect sensitive actions from brute force attacks.

API
---
Expand Down
10 changes: 10 additions & 0 deletions Test/Case/AllAttemptTest.php
@@ -0,0 +1,10 @@
<?php
class AllAttemptTest extends CakeTestSuite {
public static function suite() {
$suite = new CakeTestSuite('All Attempt Plugin Tests');
$suite->addTestDirectory(APP.'Plugin'.DS.'Attempt'.DS.'Test'.DS.'Case'.DS.'Controller'.DS.'Component');
$suite->addTestDirectory(APP.'Plugin'.DS.'Attempt'.DS.'Test'.DS.'Case'.DS.'Model');
// $suite->addTestDirectoryRecursive(APP.'Plugin'.DS.'Attempt'.DS.'Test'.DS.'Case');
return $suite;
}
}
94 changes: 94 additions & 0 deletions Test/Case/Controller/Component/AttemptComponentTest.php
@@ -0,0 +1,94 @@
<?php
App::uses('Controller', 'Controller');
App::uses('ComponentCollection', 'Controller');
App::uses('AttemptComponent', 'Attempt.Controller/Component');

/**
* TestProjectsController *
*/
class TestAttemptController extends Controller {
public $autoRender = false;
}

/**
* ProjectsController Test Case
*
*/
class AttemptComponentTestCase extends CakeTestCase {

public $AttemptComponent = null;
public $Controller = null;

public $fixtures = array('plugin.attempt.attempt');

/**
* setUp method
*
* @return void
*/
public function setUp() {
parent::setUp();

$Collection = new ComponentCollection();
$this->AttemptComponent = new AttemptComponent($Collection);

$request = new CakeRequest();
$this->Controller = new TestAttemptController($request);
$this->AttemptComponent->startup($this->Controller);
}

/**
* tearDown method
*
* @return void
*/
public function tearDown() {
parent::tearDown();
unset($this->AttemptComponent);
unset($this->Controller);
}

public function testCount() {
$result = $this->AttemptComponent->count('admin_login');
$this->assertEquals(2, $result);

$result = $this->AttemptComponent->count('something');
$this->assertEquals(0, $result);
}

public function testLimit() {
$result = $this->AttemptComponent->limit('admin_login');
$this->assertTrue($result);

$result = $this->AttemptComponent->limit('admin_login', 2);
$this->assertFalse($result);

$result = $this->AttemptComponent->limit('something', 3);
$this->assertTrue($result);
}

public function testFail() {
$result = $this->AttemptComponent->fail('admin_login');
$this->assertEquals($result['Attempt']['ip'], '127.0.0.1');
$this->assertEquals($result['Attempt']['action'], 'admin_login');

$result = $this->AttemptComponent->fail('admin_login', '+20 minutes');
$this->assertEquals($result['Attempt']['ip'], '127.0.0.1');
$this->assertEquals($result['Attempt']['action'], 'admin_login');
}

public function testReset() {
$result = $this->AttemptComponent->reset('admin_login');
$this->assertTrue($result);

// deleteAll returns true no matter what.
$result = $this->AttemptComponent->reset('something');
$this->assertTrue($result);
}

public function testCleanup() {
$result = $this->AttemptComponent->cleanup();
$this->assertTrue($result);
}

}
82 changes: 82 additions & 0 deletions Test/Case/Model/AttemptTest.php
@@ -0,0 +1,82 @@
<?php
// App::uses('Attempt', 'Attempt.Model');

/**
* Attempt Test Case
*
*/
class AttemptTestCase extends CakeTestCase {
/**
* Fixtures
*
* @var array
*/
public $fixtures = array('plugin.attempt.attempt');

/**
* setUp method
*
* @return void
*/
public function setUp() {
parent::setUp();
$this->Attempt = ClassRegistry::init('Attempt.Attempt');
}

/**
* tearDown method
*
* @return void
*/
public function tearDown() {
unset($this->Attempt);

parent::tearDown();
}

public function testCount() {
$result = $this->Attempt->count('127.0.0.1', 'admin_login');
$this->assertEquals(2, $result);

$result = $this->Attempt->count('127.0.0.7', 'admin_something');
$this->assertEquals(0, $result);
}

public function testLimit() {
$result = $this->Attempt->limit('127.0.0.1', 'admin_login', 5);
$this->assertTrue($result);

$result = $this->Attempt->limit('127.0.0.1', 'admin_login', 1);
$this->assertFalse($result);

$result = $this->Attempt->limit('127.0.0.1', 'admin_login', 0);
$this->assertFalse($result);

$result = $this->Attempt->limit('127.0.0.7', 'admin_something', 5);
$this->assertTrue($result);

$result = $this->Attempt->limit('127.0.0.7', 'admin_something', 0);
$this->assertFalse($result);
}

public function testFail() {
$result = $this->Attempt->fail('127.0.0.1', 'admin_login', '1 hour');
$this->assertEquals($result['Attempt']['ip'], '127.0.0.1');
$this->assertEquals($result['Attempt']['action'], 'admin_login');
}

public function testReset() {
$result = $this->Attempt->reset('127.0.0.1', 'admin_login');
$this->assertTrue($result);

// deleteAll returns true no matter what.
$result = $this->Attempt->reset('127.0.0.9', 'admin_something');
$this->assertTrue($result);
}

public function testCleanup() {
$result = $this->Attempt->cleanup();
$this->assertTrue($result);
}

}
51 changes: 51 additions & 0 deletions Test/Fixture/AttemptFixture.php
@@ -0,0 +1,51 @@
<?php
/**
* AttemptFixture
*
*/
class AttemptFixture extends CakeTestFixture {

/**
* Fields
*
* @var array
*/
public $fields = array(
'id' => array('type' => 'string', 'null' => false, 'length' => 36, 'key' => 'primary', 'collate' => 'utf8_general_ci', 'charset' => 'utf8'),
'ip' => array('type' => 'string', 'null' => true, 'default' => NULL, 'length' => 64, 'key' => 'index', 'collate' => 'utf8_general_ci', 'charset' => 'utf8'),
'action' => array('type' => 'string', 'null' => true, 'default' => NULL, 'length' => 32, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'),
'created' => array('type' => 'datetime', 'null' => true, 'default' => NULL),
'expires' => array('type' => 'datetime', 'null' => true, 'default' => NULL, 'key' => 'index'),
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1), 'ip' => array('column' => array('ip', 'action'), 'unique' => 0), 'expires' => array('column' => 'expires', 'unique' => 0)),
'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'MyISAM')
);

/**
* Records
*
* @var array
*/
public $records = array(
array(
'id' => '4f5a6edd-311c-43ab-8d38-464d3c87f3ee',
'ip' => '127.0.0.1',
'action' => 'admin_login',
'created' => '2012-03-09 20:58:05',
'expires' => '2012-03-09 20:58:05'
),
array(
'id' => '5f5a6edd-311c-43ab-8d38-464d3c87f3ee',
'ip' => '127.0.0.1',
'action' => 'admin_login',
'created' => '2022-03-09 20:58:07',
'expires' => '2022-03-09 20:58:07'
),
array(
'id' => '6f5a6edd-311c-43ab-8d38-464d3c87f3ee',
'ip' => '127.0.0.1',
'action' => 'admin_login',
'created' => '2015-03-09 20:58:05',
'expires' => '2015-03-09 20:58:05'
),
);
}

0 comments on commit 6ab7a2c

Please sign in to comment.