Add normalized email 1

This commit is contained in:
Visman 2019-12-26 01:21:58 +07:00
parent c476b32080
commit 4205a69c3e
16 changed files with 149 additions and 103 deletions

View file

@ -14,6 +14,12 @@ class DataModel extends Model
*/
protected $modified = [];
/**
* Массив состояний отслеживания изменений в свойствах модели
* @var array
*/
protected $track = [];
/**
* Устанавливает значения для свойств
* Флаги модификации свойст сброшены
@ -27,6 +33,7 @@ class DataModel extends Model
$this->a = $attrs; //????
$this->aCalc = [];
$this->modified = [];
$this->track = [];
return $this;
}
@ -78,6 +85,7 @@ class DataModel extends Model
public function resModified()
{
$this->modified = [];
$this->track = [];
}
/**
@ -105,8 +113,12 @@ class DataModel extends Model
}
}
$this->track[$name] = $track;
parent::__set($name, $val);
unset($this->track[$name]);
if (null === $track) {
return;
}
@ -127,9 +139,11 @@ class DataModel extends Model
*/
public function __get($name)
{
// без вычисления
if (\strpos($name, '__') === 0) {
$name = \substr($name, 2);
return isset($this->a[$name]) ? $this->a[$name] : null;
// с вычислениями
} else {
return parent::__get($name);
}

View file

@ -102,7 +102,7 @@ abstract class Users extends Admin
$this->rules = $this->c->UsersRules->init();
}
$userList = $this->c->users->load($selected);
$userList = $this->c->users->load(...$selected);
$result = [];
foreach ($userList as $user) {
if (! $user instanceof User) {

View file

@ -82,7 +82,7 @@ class Action extends Users
return $message;
}
$this->userList = $this->c->users->load($ids);
$this->userList = $this->c->users->load(...$ids);
switch ($args['action']) {
case self::ACTION_BAN:
return $this->ban($args, $method);

View file

@ -4,6 +4,7 @@ namespace ForkBB\Models\Pages\Admin\Users;
use ForkBB\Core\Validator;
use ForkBB\Models\Pages\Admin\Users;
use ForkBB\Models\User\Model as User;
class Result extends Users
{
@ -29,14 +30,14 @@ class Result extends Users
return $this->c->Message->message('Bad request');
}
$ids = $this->forIP($data['ip']);
$idsN = $this->forIP($data['ip']);
$crName = $data['ip'];
} else {
$ids = $this->forFilter($data);
$idsN = $this->forFilter($data);
$crName = \ForkBB\__('Results head');
}
$number = \count($ids);
$number = \count($idsN);
if (0 == $number) {
$view = $this->c->AdminUsers;
$view->fIswev = ['i', \ForkBB\__('No users found')];
@ -96,8 +97,29 @@ class Result extends Users
}
$startNum = ($page - 1) * $this->c->config->o_disp_users;
$ids = \array_slice($ids, $startNum, $this->c->config->o_disp_users);
$userList = $this->c->users->load($ids);
$idsN = \array_slice($idsN, $startNum, $this->c->config->o_disp_users);
$ids = [];
$userList = [];
foreach ($idsN as $cur) {
if (\is_int($cur)) {
$ids[] = $cur;
}
$userList[$cur] = $cur;
}
if (! empty($ids)) {
$idsN = $this->c->users->load(...$ids);
if (! \is_array($idsN)) {
$idsN = [$idsN];
}
foreach ($idsN as $cur) {
if ($cur instanceof User) {
$userList[$cur->id] = $cur;
}
}
}
$this->nameTpl = 'admin/users_result';
$this->mainSuffix = '-one-column';

View file

@ -147,7 +147,7 @@ class Auth extends Page
public function vLoginProcess(Validator $v, $password)
{
if (! empty($v->getErrors())) {
} elseif (! ($user = $this->c->users->load($v->username, 'username')) instanceof User
} elseif (! ($user = $this->c->users->load($this->c->users->create(['username' => $v->username]))) instanceof User
|| $user->isGuest
) {
$v->addError('Wrong user/pass');
@ -309,7 +309,7 @@ class Auth extends Page
public function changePass(array $args, $method)
{
if (! \hash_equals($args['hash'], $this->c->Secury->hash($args['email'] . $args['key']))
|| ! ($user = $this->c->users->load($args['email'], 'email')) instanceof User
|| ! ($user = $this->c->users->load($this->c->users->create(['email' => $args['email']]))) instanceof User
|| $user->isGuest
|| empty($user->activate_string)
|| ! \hash_equals($user->activate_string, $args['key'])

View file

@ -141,7 +141,7 @@ class Install extends Page
'dbprefix' => 'string:trim|max:40|check_prefix',
'username' => 'required|string:trim|min:2|max:25',
'password' => 'required|string|min:16|password',
'email' => 'required|string:trim,lower|max:80|email',
'email' => 'required|string:trim|max:80|email',
'title' => 'required|string:trim|max:255',
'descr' => 'string:trim|max:65000 bytes',
'baseurl' => 'required|string:trim|rtrim_url',
@ -498,7 +498,7 @@ class Install extends Page
'id' => ['SERIAL', false],
'username' => ['VARCHAR(190)', false, ''],
'ip' => ['VARCHAR(255)', false, ''],
'email' => ['VARCHAR(80)', false, ''],
'email' => ['VARCHAR(190)', false, ''],
'message' => ['VARCHAR(255)', false, ''],
'expire' => ['INT(10) UNSIGNED', false, 0],
'ban_creator' => ['INT(10) UNSIGNED', false, 0],
@ -653,7 +653,7 @@ class Install extends Page
'poster' => ['VARCHAR(190)', false, ''],
'poster_id' => ['INT(10) UNSIGNED', false, 1],
'poster_ip' => ['VARCHAR(45)', false, ''],
'poster_email' => ['VARCHAR(80)', false, ''],
'poster_email' => ['VARCHAR(190)', false, ''],
'message' => ['MEDIUMTEXT', false, ''],
'hide_smilies' => ['TINYINT(1)', false, 0],
'edit_post' => ['TINYINT(1)', false, 0],
@ -868,7 +868,8 @@ class Install extends Page
'group_id' => ['INT(10) UNSIGNED', false, 0],
'username' => ['VARCHAR(190)', false, ''],
'password' => ['VARCHAR(255)', false, ''],
'email' => ['VARCHAR(80)', false, ''],
'email' => ['VARCHAR(190)', false, ''],
'email_normal' => ['VARCHAR(190)', false, ''],
'email_confirmed' => ['TINYINT(1)', false, 0],
'title' => ['VARCHAR(50)', false, ''],
'realname' => ['VARCHAR(40)', false, ''],
@ -920,8 +921,8 @@ class Install extends Page
],
'PRIMARY KEY' => ['id'],
'UNIQUE KEYS' => [
'username_idx' => ['username(25)'],
'email_idx' => ['email'],
'username_idx' => ['username(25)'],
'email_normal_idx' => ['email_normal'],
],
'INDEXES' => [
'registered_idx' => ['registered'],
@ -1035,8 +1036,8 @@ class Install extends Page
$this->c->DB->exec('UPDATE ::groups SET g_pm_limit=0 WHERE g_id=?i', [$this->c->GROUP_ADMIN]);
$ip = \filter_var($_SERVER['REMOTE_ADDR'], \FILTER_VALIDATE_IP) ?: 'unknow';
$this->c->DB->exec('INSERT INTO ::users (group_id, username, password, email) VALUES (?i, ?s, ?s, ?s)', [$this->c->GROUP_GUEST, \ForkBB\__('Guest '), \ForkBB\__('Guest '), \ForkBB\__('Guest ')]);
$this->c->DB->exec('INSERT INTO ::users (group_id, username, password, email, language, style, num_posts, last_post, registered, registration_ip, last_visit) VALUES (?i, ?s, ?s, ?s, ?s, ?s, ?i, ?i, ?i, ?s, ?i)', [$this->c->GROUP_ADMIN, $v->username, password_hash($v->password, \PASSWORD_DEFAULT), $v->email, $v->defaultlang, $v->defaultstyle, 1, $now, $now, $ip, $now]);
$this->c->DB->exec('INSERT INTO ::users (group_id, username, password) VALUES (?i, ?s, ?s)', [$this->c->GROUP_GUEST, \ForkBB\__('Guest '), \ForkBB\__('Guest ')]);
$this->c->DB->exec('INSERT INTO ::users (group_id, username, password, email, email_normal, language, style, num_posts, last_post, registered, registration_ip, last_visit) VALUES (?i, ?s, ?s, ?s, ?s, ?s, ?s, ?i, ?i, ?i, ?s, ?i)', [$this->c->GROUP_ADMIN, $v->username, password_hash($v->password, \PASSWORD_DEFAULT), $v->email, $this->c->NormEmail->normalize($v->email), $v->defaultlang, $v->defaultstyle, 1, $now, $now, $ip, $now]);
$pun_config = [
'i_fork_revision' => $this->c->FORK_REVISION,

View file

@ -18,7 +18,7 @@ class Message extends Page
public function message($message, $back = true, $status = 404, array $headers = [])
{
$this->nameTpl = 'message';
$this->httpStatus = $status;
$this->httpStatus = \max(200, $status);
$this->httpHeaders = $headers;
$this->titles = \ForkBB\__('Info');
$this->back = $back;

View file

@ -24,7 +24,7 @@ class Register extends Page
'token' => 'token:RegisterForm',
'agree' => 'required|token:Register',
'on' => 'integer',
'email' => 'required_with:on|string:trim,lower|email:noban,unique',
'email' => 'required_with:on|string:trim|email:noban,unique',
'username' => 'required_with:on|string:trim,spaces|username',
'password' => 'required_with:on|string|min:16|password',
])->addAliases([

View file

@ -92,7 +92,7 @@ class Userlist extends Page
if ($number) {
$this->startNum = ($page - 1) * $this->c->config->o_disp_users;
$ids = \array_slice($ids, $this->startNum, $this->c->config->o_disp_users);
$this->userList = $this->c->users->load($ids);
$this->userList = $this->c->users->load(...$ids);
$links = [];
$vars = ['page' => $page];

View file

@ -177,7 +177,8 @@ class View extends Action
}
}
$this->c->users->load(\array_keys($userIds));
$ids = \array_keys($userIds);
$this->c->users->load(...$ids);
$offset = ($arg->page - 1) * $this->c->user->disp_posts;
$timeMax = 0;
@ -191,7 +192,7 @@ class View extends Action
if ($arg instanceof Topic) {
foreach ($result as $post) {
if ($post->id === $arg->last_post_id) { // время последнего сообщения в теме может равняться
if ($post->id === $arg->last_post_id) { // время последнего сообщения в теме может равняться
$timeMax = $arg->last_post; // времени его редактирования, а не создания
} elseif ($post->posted > $timeMax) {
$timeMax = $post->posted;

View file

@ -3,46 +3,41 @@
namespace ForkBB\Models\User;
use ForkBB\Models\Action;
use ForkBB\Models\User\Model as User;
use InvalidArgumentException;
class Load extends Action
{
/**
* Получение пользователя по условию
* Получение пользователя
*
* @param mixed $value
* @param string $field
*
* @throws InvalidArgumentException
*
* @return mixed
*/
public function load($value, $field = 'id')
public function load($value)
{
$flag = \is_array($value);
switch (($flag ? 'a_' : '') . $field) {
case 'id':
$where = 'u.id=?i:field';
break;
case 'username':
if (\is_array($value)) {
$where = 'u.id IN (?ai:field)';
} elseif ($value instanceof User) {
if ('' != $value->username) {
$where = 'u.username=?s:field';
break;
case 'email':
$value = $value->username;
} elseif ('' != $value->email) {
$where = 'u.email=?s:field';
break;
case 'a_id':
$where = 'u.id IN (?ai:field)';
break;
case 'a_username':
$where = 'u.username IN (?as:field)';
break;
case 'a_email':
$where = 'u.email IN (?as:field)';
break;
default:
$value = $value->email;
} elseif ('' != $value->email_normal) {
$where = 'u.email_normal=?s:field';
$value = $value->email_normal;
} else {
throw new InvalidArgumentException('Field not supported');
}
} else {
$where = 'u.id=?i:field';
}
$vars = [':field' => $value];
$sql = 'SELECT u.*, g.*
FROM ::users AS u
@ -51,19 +46,10 @@ class Load extends Action
$data = $this->c->DB->query($sql, $vars)->fetchAll();
if ($flag) {
$result = [];
foreach ($data as $row) {
$result[] = $this->manager->create($row);
}
return $result;
} else {
$count = \count($data);
// число найденных пользователей отлично от одного
if (1 !== $count) {
return $count;
}
return $this->manager->create($data[0]);
$result = [];
foreach ($data as $row) {
$result[] = $this->manager->create($row);
}
return $result;
}
}

View file

@ -4,7 +4,7 @@ namespace ForkBB\Models\User;
use ForkBB\Models\ManagerModel;
use ForkBB\Models\User\Model as User;
use RuntimeException;
use InvalidArgumentException;
class Manager extends ManagerModel
{
@ -21,34 +21,55 @@ class Manager extends ManagerModel
}
/**
* Получение пользователя по условию
* Получение пользователя(ей) по id, массиву id или по модели User
*
* @param mixed $value
* @param string $field
* @param mixed ...$args
*
* @throws InvalidArgumentException
*
* @return mixed
*/
public function load($value, $field = 'id')
public function load(...$args)
{
if (\is_array($value)) {
$result = \array_flip($value); // ???? а если пользователь не найдется?
if ('id' === $field) {
$temp = [];
foreach ($value as $id) {
if (\is_string($id)) { // ???? для пользователей из админки
$result[$id] = $id;
} elseif ($this->get($id) instanceof User) {
$result[$id] = $this->get($id);
} else {
$temp[] = $id;
}
$result = [];
$count = \count($args);
$countID = 0;
$countUser = 0;
$reqIDs = [];
$error = false;
$user = null;
foreach ($args as $arg) {
if ($arg instanceof User) {
++$countUser;
$user = $arg;
} elseif (\is_int($arg) && $arg > 0) {
++$countID;
if ($this->get($arg) instanceof User) {
$result[$arg] = $this->get($arg);
} else {
$result[$arg] = false;
$reqIDs[] = $arg;
}
$value = $temp;
} else {
$error = true;
}
if (empty($value)) {
return $result;
}
if ($error || $countUser * $countID > 0 || $countUser > 1 || ($countID > 0 && $count > $countID)) {
throw new InvalidArgumentException('Expected only integer, integer array or User');
}
if (! empty($reqIDs) || null !== $user) {
if (null !== $user) {
$data = $user;
} elseif (1 === \count($reqIDs)) {
$data = \array_pop($reqIDs);
} else {
$data = $reqIDs;
}
foreach ($this->Load->load($value, $field) as $user) {
foreach ($this->Load->load($data) as $user) {
if ($user instanceof User) {
if ($this->get($user->id) instanceof User) {
$result[$user->id] = $this->get($user->id);
@ -58,27 +79,9 @@ class Manager extends ManagerModel
}
}
}
return $result;
} else {
$user = 'id' === $field ? $this->get($value) : null;
if (! $user instanceof User) {
$user = $this->Load->load($value, $field);
if ($user instanceof User) {
$test = $this->get($user->id);
if ($test instanceof User) {
return $test;
}
$this->set($user->id, $user);
}
}
return $user;
}
return 1 === \count($result) ? \array_pop($result) : $result;
}
/**

View file

@ -365,4 +365,19 @@ class Model extends DataModel
return null;
}
}
/**
* Установка email и вычисление нормализованного email
*
* @param string $email
*/
protected function setemail($email)
{
$this->a['email'] = $email;
if (isset($email[0])) {
$property = (! isset($this->track['email']) ? '__' : '') . 'email_normal';
$this->$property = $this->c->NormEmail->normalize($email);
}
}
}

View file

@ -47,8 +47,8 @@ class Email extends Validators
$ok = false;
}
// отсутствует пользователь с таким email (или их больше одного O_o)
if (isset($attrs['exists'])) {
$user = $this->c->users->load($email, 'email');
if ($ok && isset($attrs['exists'])) {
$user = $this->c->users->load($this->c->users->create(['email_normal' => $this->c->NormEmail->normalize($email)]));
if (! $user instanceof User) {
$v->addError('Invalid email');
@ -58,12 +58,14 @@ class Email extends Validators
// email не уникален
if ($ok && isset($attrs['unique']) && (! $originalUser instanceof User || ! $originalUser->isGuest)) {
if (true === $user) {
$user = $this->c->users->load($email, 'email');
$user = $this->c->users->load($this->c->users->create(['email_normal' => $this->c->NormEmail->normalize($email)]));
}
$id = $originalUser instanceof User ? $originalUser->id : true;
if (($user instanceof User && $id !== $user->id) || (! $user instanceof User && 0 !== $user)) {
if (($user instanceof User && $id !== $user->id)
|| (\is_array($user) && \count($user) > 1) // ???? эта ветка не реальна? поле email_normal уникально
) {
$v->addError('Dupe email');
$ok = false;
}

View file

@ -82,6 +82,7 @@ return [
'eol' => '%EOL%',
],
'Func' => \ForkBB\Core\Func::class,
'NormEmail' => \MioVisman\NormEmail\NormEmail::class,
'Csrf' => [
'class' => \ForkBB\Core\Csrf::class,
'Secury' => '@Secury',

View file

@ -84,6 +84,7 @@ return [
'eol' => '%EOL%',
],
'Func' => \ForkBB\Core\Func::class,
'NormEmail' => \MioVisman\NormEmail\NormEmail::class,
'config' => '@ConfigModel:init',
'bans' => '@BanListModel:init',