浏览代码

DirectAuth improvements and Qlogin

euromark 13 年之前
父节点
当前提交
27b6426d51

+ 2 - 2
Controller/Component/Auth/DirectAuthenticate.php

@@ -19,7 +19,7 @@ App::uses('BaseAuthenticate', 'Controller/Component/Auth');
  *   in your AppController just as any other adapter.
  *   in your AppController just as any other adapter.
  *
  *
  * @author Mark Scherer
  * @author Mark Scherer
- * @licente MIT
+ * @license MIT
  * @cakephp 2.x (>= 2.3)
  * @cakephp 2.x (>= 2.3)
  * 2012-11-05 ms
  * 2012-11-05 ms
  */
  */
@@ -74,7 +74,7 @@ class DirectAuthenticate extends BaseAuthenticate {
 	 * @param array $conditions An array of find conditions.
 	 * @param array $conditions An array of find conditions.
 	 * @return Mixed Either false on failure, or an array of user data.
 	 * @return Mixed Either false on failure, or an array of user data.
 	 */
 	 */
-	protected function _findUser($conditions) {
+	protected function _findUser($conditions, $password = null) {
 		$userModel = $this->settings['userModel'];
 		$userModel = $this->settings['userModel'];
 		list($plugin, $model) = pluginSplit($userModel);
 		list($plugin, $model) = pluginSplit($userModel);
 		$fields = $this->settings['fields'];
 		$fields = $this->settings['fields'];

+ 6 - 8
Controller/Component/AuthExtComponent.php

@@ -49,7 +49,7 @@ class AuthExtComponent extends AuthComponent {
 	public $settings = array(
 	public $settings = array(
 		'multi' => null, # null=auto - yes/no multiple roles (HABTM table between users and roles)
 		'multi' => null, # null=auto - yes/no multiple roles (HABTM table between users and roles)
 		'parentModelAlias' => USER_ROLE_KEY,
 		'parentModelAlias' => USER_ROLE_KEY,
-		'userModel' => CLASS_USER
+		'userModel' => CLASS_USER //TODO: allow plugin syntax
 	);
 	);
 
 
 	# field name in DB , if none is specified there will be no floodProtection
 	# field name in DB , if none is specified there will be no floodProtection
@@ -58,7 +58,6 @@ class AuthExtComponent extends AuthComponent {
 
 
 	public function __construct(ComponentCollection $Collection, $settings = array()) {
 	public function __construct(ComponentCollection $Collection, $settings = array()) {
 		$settings = array_merge($this->settings, (array)Configure::read('Auth'), (array)$settings);
 		$settings = array_merge($this->settings, (array)Configure::read('Auth'), (array)$settings);
-		//$this->Controller = $Collection->getController();
 
 
 		parent::__construct($Collection, $settings);
 		parent::__construct($Collection, $settings);
 	}
 	}
@@ -163,7 +162,7 @@ class AuthExtComponent extends AuthComponent {
 	}
 	}
 
 
 	/**
 	/**
-	 * return array $user or bool false on failure
+	 * @return array $user or bool false on failure
 	 * 2011-11-03 ms
 	 * 2011-11-03 ms
 	 */
 	 */
 	public function completeAuth($user) {
 	public function completeAuth($user) {
@@ -264,7 +263,7 @@ class AuthExtComponent extends AuthComponent {
 	 */
 	 */
 	public function startup(Controller $controller) {
 	public function startup(Controller $controller) {
 		//parent::startup($controller);
 		//parent::startup($controller);
-		if ($controller->name == 'CakeError') {
+		if ($controller->name === 'CakeError') {
 			return true;
 			return true;
 		}
 		}
 
 
@@ -342,13 +341,11 @@ class AuthExtComponent extends AuthComponent {
 	}
 	}
 
 
 	/**
 	/**
-	 * Quickfix
-	 * TODO: improve - maybe use Authenticate
 	 * @deprecated
 	 * @deprecated
 	 * @return bool $success
 	 * @return bool $success
 	 */
 	 */
 	public function verifyUser($id, $pwd) {
 	public function verifyUser($id, $pwd) {
-		//trigger_error('deprecated - use Authenticate class');
+		trigger_error('deprecated - use Authenticate class');
 		$options = array(
 		$options = array(
 			'conditions' => array('id'=>$id, 'password'=>$this->password($pwd)),
 			'conditions' => array('id'=>$id, 'password'=>$this->password($pwd)),
 		);
 		);
@@ -364,7 +361,8 @@ class AuthExtComponent extends AuthComponent {
 	 * @return object $User
 	 * @return object $User
 	 */
 	 */
 	public function getModel() {
 	public function getModel() {
-		return ClassRegistry::init(CLASS_USER);
+		$model = $this->settings['userModel'];
+		return ClassRegistry::init($model);
 	}
 	}
 
 
 }
 }

+ 4 - 5
Controller/Component/CommonComponent.php

@@ -386,15 +386,14 @@ class CommonComponent extends Component {
 	 * @return boolean Success
 	 * @return boolean Success
 	 * 2012-11-05 ms
 	 * 2012-11-05 ms
 	 */
 	 */
-	public function manualLogin($id, $contain = array()) {
+	public function manualLogin($id, $settings = array()) {
 		$requestData = $this->Controller->request->data;
 		$requestData = $this->Controller->request->data;
 		$authData = $this->Controller->Auth->authenticate;
 		$authData = $this->Controller->Auth->authenticate;
-		if (!$contain && !empty($authData['Form']['contain'])) {
-			$contain = $authData['Form']['contain'];
-		}
+		$settings = array_merge($authData, $settings);
+		$settings['fields'] = array('username' => 'id');
 
 
 		$this->Controller->request->data = array('User' => array('id' => $id));
 		$this->Controller->request->data = array('User' => array('id' => $id));
-		$this->Controller->Auth->authenticate = array('Tools.Direct'=>array('contain' => $contain, 'fields'=>array('username' => 'id')));
+		$this->Controller->Auth->authenticate = array('Tools.Direct' => $settings);
 		$result = $this->Controller->Auth->login();
 		$result = $this->Controller->Auth->login();
 
 
 		$this->Controller->Auth->authenticate = $authData;
 		$this->Controller->Auth->authenticate = $authData;

+ 5 - 9
Controller/QloginController.php

@@ -49,19 +49,15 @@ class QloginController extends ToolsAppController {
 		$url = $entry['CodeKey']['url'];
 		$url = $entry['CodeKey']['url'];
 
 
 		if (!$this->Session->read('Auth.User.id')) {
 		if (!$this->Session->read('Auth.User.id')) {
-			$this->User = ClassRegistry::init(CLASS_USER);
-			# needs to be logged in
-			$user = $this->User->get($uid);
-			if (!$user) {
-				$this->Common->flashMessage(__('Invalid Account'), 'error');
-				$this->Common->autoRedirect($default);
-			}
-
-			if ($this->Auth->login($user['User'])) {
+			if ($this->Common->manualLogin($uid)) {
 				$this->Session->write('Auth.User.Login.qlogin', true);
 				$this->Session->write('Auth.User.Login.qlogin', true);
 				if (!Configure::read('Qlogin.suppressMessage')) {
 				if (!Configure::read('Qlogin.suppressMessage')) {
 					$this->Common->flashMessage(__('You successfully logged in via qlogin'), 'success');
 					$this->Common->flashMessage(__('You successfully logged in via qlogin'), 'success');
 				}
 				}
+			} else {
+				$this->Common->flashMessage($this->Auth->loginError, 'error');
+				$url = $default;
+				trigger_error($this->Auth->loginError . ' - uid ' . $uid);
 			}
 			}
 		}
 		}
 		$this->redirect($url);
 		$this->redirect($url);

+ 40 - 7
Model/Behavior/PasswordableBehavior.php

@@ -134,12 +134,15 @@ class PasswordableBehavior extends ModelBehavior {
 			throw new CakeException('No validation class found');
 			throw new CakeException('No validation class found');
 		}
 		}
 		# easiest authenticate method via form and (id + pwd)
 		# easiest authenticate method via form and (id + pwd)
-		$this->Auth->authenticate = array('Form'=>array('fields'=>array('username' => 'id', 'password'=>$this->settings[$Model->alias]['field'])));
-
+		$this->Auth->authenticate = array(
+			'Form' => array(
+				'fields'=>array('username' => 'id', 'password'=>$this->settings[$Model->alias]['field'])
+			)
+		);
 		$request = new CakeRequest(null, false);
 		$request = new CakeRequest(null, false);
 		$request->data['User'] = array('id'=>$uid, 'password'=>$pwd);
 		$request->data['User'] = array('id'=>$uid, 'password'=>$pwd);
 		$response = new CakeResponse();
 		$response = new CakeResponse();
-		return $this->Auth->identify($request, $response);
+		return (bool)$this->Auth->identify($request, $response);
 	}
 	}
 
 
 	/**
 	/**
@@ -154,7 +157,7 @@ class PasswordableBehavior extends ModelBehavior {
 			$value = $data;
 			$value = $data;
 		}
 		}
 		$compareValue = $Model->data[$Model->alias][$compareWith];
 		$compareValue = $Model->data[$Model->alias][$compareWith];
-		return ($compareValue == $value);
+		return ($compareValue === $value);
 	}
 	}
 
 
 	/**
 	/**
@@ -165,7 +168,29 @@ class PasswordableBehavior extends ModelBehavior {
 	public function validateNotSame(Model $Model, $data, $field1, $field2) {
 	public function validateNotSame(Model $Model, $data, $field1, $field2) {
 		$value1 = $Model->data[$Model->alias][$field1];
 		$value1 = $Model->data[$Model->alias][$field1];
 		$value2 = $Model->data[$Model->alias][$field2];
 		$value2 = $Model->data[$Model->alias][$field2];
-		return ($value1 != $value2);
+		return ($value1 !== $value2);
+	}
+
+	/**
+	 * if not implemented in AppModel
+	 * @return bool $success
+	 * 2011-11-10 ms
+	 */
+	public function validateNotSameHash(Model $Model, $data, $formField) {
+		$field = $this->settings[$Model->alias]['field'];
+		$type = $this->settings[$Model->alias]['hashType'];
+		$salt = $this->settings[$Model->alias]['hashSalt'];
+
+		if (!isset($Model->data[$Model->alias][$Model->primaryKey])) {
+			return true;
+		}
+		$primaryKey = $Model->data[$Model->alias][$Model->primaryKey];
+		$value = Security::hash($Model->data[$Model->alias][$formField], $type, $salt);
+		$dbValue = $Model->field($field, array($Model->primaryKey => $primaryKey));
+		if (!$dbValue) {
+			return true;
+		}
+		return ($value !== $dbValue);
 	}
 	}
 
 
 	/**
 	/**
@@ -196,7 +221,6 @@ class PasswordableBehavior extends ModelBehavior {
 			$Model->validate[$formFieldRepeat]['validateIdentical']['rule'][1] = $formField;
 			$Model->validate[$formFieldRepeat]['validateIdentical']['rule'][1] = $formField;
 		}
 		}
 
 
-
 		if ($this->settings[$Model->alias]['current'] && !isset($Model->validate[$formFieldCurrent])) {
 		if ($this->settings[$Model->alias]['current'] && !isset($Model->validate[$formFieldCurrent])) {
 			$Model->validate[$formFieldCurrent] = $rules['formFieldCurrent'];
 			$Model->validate[$formFieldCurrent] = $rules['formFieldCurrent'];
 
 
@@ -208,6 +232,16 @@ class PasswordableBehavior extends ModelBehavior {
 					'last' => true,
 					'last' => true,
 				);
 				);
 			}
 			}
+		} elseif (!isset($Model->validate[$formFieldCurrent])) {
+			# try to match the password against the hash in the DB
+			if (!$this->settings[$Model->alias]['allowSame']) {
+				$Model->validate[$formField]['validateNotSame'] = array(
+					'rule' => array('validateNotSameHash', $formField),
+					'message' => 'valErrPwdSameAsBefore',
+					'allowEmpty' => $this->settings[$Model->alias]['allowEmpty'],
+					'last' => true,
+				);
+			}
 		}
 		}
 	}
 	}
 
 
@@ -276,7 +310,6 @@ class PasswordableBehavior extends ModelBehavior {
 	 * 2011-07-22 ms
 	 * 2011-07-22 ms
 	 */
 	 */
 	public function beforeSave(Model $Model) {
 	public function beforeSave(Model $Model) {
-		//debug($Model->data);
 		$formField = $this->settings[$Model->alias]['formField'];
 		$formField = $this->settings[$Model->alias]['formField'];
 		$field = $this->settings[$Model->alias]['field'];
 		$field = $this->settings[$Model->alias]['field'];
 		$type = $this->settings[$Model->alias]['hashType'];
 		$type = $this->settings[$Model->alias]['hashType'];

+ 59 - 12
Test/Case/Model/Behavior/PasswordableBehaviorTest.php

@@ -1,6 +1,4 @@
 <?php
 <?php
-//App::uses('Model', 'Model');
-//App::uses('AppModel', 'Model');
 App::uses('ComponentCollection', 'Controller');
 App::uses('ComponentCollection', 'Controller');
 
 
 class PasswordableBehaviorTest extends CakeTestCase {
 class PasswordableBehaviorTest extends CakeTestCase {
@@ -16,6 +14,18 @@ class PasswordableBehaviorTest extends CakeTestCase {
 		parent::setUp();
 		parent::setUp();
 
 
 		$this->User = ClassRegistry::init('User');
 		$this->User = ClassRegistry::init('User');
+		if (isset($this->User->validate['pwd'])) {
+			unset($this->User->validate['pwd']);
+		}
+		if (isset($this->User->validate['pwd_repeat'])) {
+			unset($this->User->validate['pwd_repeat']);
+		}
+		if (isset($this->User->validate['pwd_current'])) {
+			unset($this->User->validate['pwd_current']);
+		}
+		if (isset($this->User->order)) {
+			unset($this->User->order);
+		}
 	}
 	}
 
 
 	/**
 	/**
@@ -31,7 +41,7 @@ class PasswordableBehaviorTest extends CakeTestCase {
 
 
 	public function testObject() {
 	public function testObject() {
 		$this->User->Behaviors->attach('Tools.Passwordable', array());
 		$this->User->Behaviors->attach('Tools.Passwordable', array());
-		$this->assertInstanceOf($this->User->Behaviors->Passwordable, 'PasswordableBehavior');
+		$this->assertInstanceOf('PasswordableBehavior', $this->User->Behaviors->Passwordable);
 		$res = $this->User->Behaviors->attached('Passwordable');
 		$res = $this->User->Behaviors->attached('Passwordable');
 		$this->assertTrue($res);
 		$this->assertTrue($res);
 	}
 	}
@@ -44,7 +54,7 @@ class PasswordableBehaviorTest extends CakeTestCase {
 
 
 		$this->User->create();
 		$this->User->create();
 		$data = array(
 		$data = array(
-			'pwd' => '1234',
+			'pwd' => '123456',
 		);
 		);
 		$this->User->set($data);
 		$this->User->set($data);
 		$is = $this->User->save();
 		$is = $this->User->save();
@@ -55,7 +65,7 @@ class PasswordableBehaviorTest extends CakeTestCase {
 
 
 		$this->User->create();
 		$this->User->create();
 		$data = array(
 		$data = array(
-			'pwd' => '1234',
+			'pwd' => '1234ab',
 			'pwd_repeat' => '123456'
 			'pwd_repeat' => '123456'
 		);
 		);
 		$this->User->set($data);
 		$this->User->set($data);
@@ -137,11 +147,6 @@ class PasswordableBehaviorTest extends CakeTestCase {
 			'pwd_current' => '',
 			'pwd_current' => '',
 		);
 		);
 		$is = $this->User->save($data);
 		$is = $this->User->save($data);
-
-		debug($this->User->data);
-		debug($this->User->validate);
-		debug($this->User->validationErrors); ob_flush();
-
 		$this->assertTrue(!empty($is));
 		$this->assertTrue(!empty($is));
 	}
 	}
 
 
@@ -203,6 +208,48 @@ class PasswordableBehaviorTest extends CakeTestCase {
 	}
 	}
 
 
 	/**
 	/**
+	 * assert that allowSame false does not allow storing the same password as previously entered
+	 */
+	public function testNotSameWithoutCurrentField() {
+		$this->User->Behaviors->attach('Tools.Passwordable', array(
+			'formField' => 'passw',
+			'formFieldRepeat' => 'passw_repeat',
+			'allowSame' => false,
+			'current' => false
+		));
+		$this->User->create();
+		$data = array(
+			'passw' => 'some',
+			'passw_repeat' => 'some'
+		);
+		$this->User->set($data);
+		$is = $this->User->save();
+		$this->assertTrue((bool)$is);
+		$id = $is['User']['id'];
+
+		$this->User->create();
+		$data = array(
+			'id' => $id,
+			'passw' => 'some',
+			'passw_repeat' => 'some'
+		);
+		$this->User->set($data);
+		$is = $this->User->save();
+		debug($this->User->validationErrors); ob_flush();
+		$this->assertFalse((bool)$is);
+
+		$this->User->create();
+		$data = array(
+			'id' => $id,
+			'passw' => 'new',
+			'passw_repeat' => 'new'
+		);
+		$this->User->set($data);
+		$is = $this->User->save();
+		$this->assertTrue((bool)$is);
+	}
+
+	/**
 	 * needs faking of pwd check...
 	 * needs faking of pwd check...
 	 */
 	 */
 	public function testValidateCurrent() {
 	public function testValidateCurrent() {
@@ -227,9 +274,9 @@ class PasswordableBehaviorTest extends CakeTestCase {
 		);
 		);
 		$this->User->set($data);
 		$this->User->set($data);
 		$this->assertTrue($this->User->Behaviors->attached('Passwordable'));
 		$this->assertTrue($this->User->Behaviors->attached('Passwordable'));
-		debug($this->User->validate); ob_flush();
+		//debug($this->User->validate); ob_flush();
 		$is = $this->User->save();
 		$is = $this->User->save();
-		//debug($this->User->validationErrors); ob_flush();
+		debug($this->User->validationErrors); ob_flush();
 		$this->assertFalse($is);
 		$this->assertFalse($is);
 
 
 		$this->User->create();
 		$this->User->create();

+ 2 - 1
View/Helper/FormExtHelper.php

@@ -579,8 +579,9 @@ class FormExtHelper extends FormHelper { // Maybe FormHelper itself some day?
 		$defaultOptions = array(
 		$defaultOptions = array(
 			'empty' => false,
 			'empty' => false,
 			'minYear' => date('Y')-10,
 			'minYear' => date('Y')-10,
-			'maxYear' => date('Y')+2
+			'maxYear' => date('Y')+10
 		);
 		);
+		$defaultOptions = array_merge($defaultOptions, (array)Configure::read('Form.date'));
 
 
 		$fieldName = Inflector::camelize($fieldName);
 		$fieldName = Inflector::camelize($fieldName);