Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save egorsmkv/48c0348762ba0d1fe8251c0799f52003 to your computer and use it in GitHub Desktop.
Save egorsmkv/48c0348762ba0d1fe8251c0799f52003 to your computer and use it in GitHub Desktop.
<?php
namespace app\models;
use yii\base\Model;
use Yii;
/**
* Simplified model with validation rules.
* All characters are allowed (you want emojis in the password? Go ahead).
* There are three basic rules for the user:
* 1) Minimum password length.
* 2) Minimum password entropy.
* 3) Don't use common names you see on the screen as password.
*
* @property string $email
*/
class User extends Model
{
const MIN_PASSWORD = 10;
const MAX_PASSWORD = 64;
const MIN_ENTROPY = 2;
/**
* @var string Raw password to be validated
*/
public $rawPassword;
/**
* @inheritdoc
*/
public function rules()
{
return [
// obviously we need these 2
[['email', 'rawPassword'], 'required'],
// email should be email, also Yii 2 limits max email size to 254 characters so we don't have to worry about that
['email', 'email'],
// email needs to be unique in database to identify user
['email', 'unique'],
// password must not be shorter than self::MIN_PASSWORD
// 10 characters minimum is required nowadays
// but it shouldn't be a problem especially when we don't force bullshit composition
// maximum limit is not that important but we should add reasonable one as well
['rawPassword', 'string', 'min' => self::MIN_PASSWORD, 'max' => self::MAX_PASSWORD],
// lazy copy-paste check: password must not be the same as user's email address
['rawPassword', 'compare', 'compareAttribute' => 'email', 'operator' => '!='],
// lazy copy-paste check: password must not be the same as application's name
['rawPassword', 'compare', 'compareValue' => Yii::$app->name, 'operator' => '!='],
// lazy copy-paste check: password must not be the same as application's URL
['rawPassword', 'compare', 'compareValue' => \yii\helpers\Url::home(), 'operator' => '!='],
// password's entropy must be greater than self::MIN_ENTROPY (the smaller number = more repetition allowed)
// some examples: 'aaaaaaaaaa' => 0, '0123456789' => 3.322
['rawPassword', function ($attribute, $params, $validator) {
$entropy = 0;
$size = mb_strlen($this->$attribute, Yii::$app->charset ?: 'UTF-8');
foreach (count_chars($this->$attribute, 1) as $frequency) {
$p = $frequency / $size;
$entropy -= $p * log($p) / log(2);
}
if ($entropy < self::MIN_ENTROPY) {
$this->addError($attribute, 'You must choose more complex password.');
}
}],
];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment