scope('profile', _t('@users', 'Your Profile'))
->method('profile')
->scope('members-listing', _t('@users', 'Users List'))
->method('listing')
->method('ajax')->action('user-info')
->scope('admins-listing', _t('@users', 'Admins List'))
->method('listing_moderators')
->scope('users-edit', _t('@users', 'Users Management'))
->method('listing')
->action('mass', function () {
return in_array($this->input->post('action'), [
'block', 'unblock', 'unfake', 'delete', 'del_empty',
], true);
})
->methods(['user_add', 'user_edit', 'user_action'])
->method('ajax')->actions([
'user-block', 'user-activate', 'user-admin-comment', 'auth-url',
])
->scope('admins-edit', _t('@users', 'Admins Management'))
->publicMethod(['login','logout'])
->seoTemplates()
;
}
/**
* Профиль пользователя
* @return string|mixed
*/
public function profile()
{
if (! $this->haveAccessTo('profile')) {
return $this->showAccessDenied();
}
if (User::guest()) {
return $this->adminRedirect(Errors::IMPOSSIBLE, 'login');
}
$userID = User::id();
if ($this->isPOST()) {
$changePassword = $this->input->post('changepass', TYPE_BOOL);
$data = $this->model->userData($userID, ['password', 'password_salt']);
$update = [];
if ($this->errors->no() && $changePassword) {
$passwordCurrent = $this->input->post('password0', TYPE_NOTRIM); # текущий пароль
$passwordNew = $this->input->post('password1', TYPE_NOTRIM); # новый пароль
$passwordRepeat = $this->input->post('password2', TYPE_NOTRIM); # новый пароль (подтверждение)
do {
if (!$passwordCurrent) {
$this->errors->set(_t('@users', 'Enter current password'), 'password0');
break;
}
if (! $this->security->passwordCheck($passwordCurrent, $data['password'], $data['password_salt'])) {
$this->errors->set(_t('@users', 'Current password is incorrect'), 'password0');
break;
}
if (empty($passwordNew) || mb_strlen($passwordNew) < $this->passwordMinLength) {
$this->errors->set(_t('@users', 'New password is too short'), 'password1');
break;
}
if ($passwordNew !== $passwordRepeat) {
$this->errors->set(_t('@users', 'Password confirmation failed'), 'password2');
break;
}
if ($this->errors->no()) {
$update['password'] = $this->security->passwordHash($passwordNew, $data['password_salt']);
}
} while (false);
}
$msg = '';
if ($this->errors->no('users.admin.profile.submit', ['id' => $userID, 'data' => &$update]) && !empty($update)) {
$this->model->userSave($userID, $update);
$msg = _t('', 'Saved successfully');
}
return $this->ajaxResponseForm(['msg' => $msg]);
}
$userGroups = $this->model->userGroups($userID);
if (empty($userGroups)) {
$userGroups = [];
}
$data = User::data(['name', 'login', 'avatar', 'email']);
$data['user_id'] = $userID;
$data['groups'] = $userGroups;
return $this->template('admin/profile', $data);
}
/**
* Выход из админ-панели
* @return mixed
*/
public function logout()
{
$redirectUrl = Admin::url('users/login');
$this->app->hook('users.user.logout', User::id(), $redirectUrl);
Auth::logout();
return $this->redirect($redirectUrl ?: '/');
}
/**
* Форма авторизации в адми-панель
* @return mixed
*/
public function login()
{
if (User::admin()) {
return $this->adminRedirect(null, 'profile');
}
$login = '';
if ($this->isPOST()) {
$login = $this->input->post('login', TYPE_STR);
if (!$login) {
$this->errors->set(_t('@users', 'Enter login'));
}
$password = $this->input->post('password', TYPE_NOTRIM);
if (!$password) {
$this->errors->set(_t('@users', 'Enter password'));
}
if ($this->errors->no('users.admin.login.step1', ['id' => 0, 'login' => $login, 'password' => $password])) {
$this->isLoginOrEmail($login, $isEmail);
$data = $this->model->userSessionData([($isEmail ? 'email' : 'login') => $login]);
if (! empty($data)) {
if (! $this->security->passwordCheck($password, $data['password'], $data['password_salt'])) {
$data = false;
}
}
if (! $data) {
$this->errors->set(_t('@users', 'Incorrect login or password'));
$userID = 0;
} else {
$userID = $data['id'];
# аккаунт заблокирован
if ($data['blocked'] == 1) {
$this->errors->set(sprintf(_t('@users', 'Account suspended: %s'), $data['blocked_reason']));
} else {
# проверка IP в бан-листе
$isBlocked = $this->checkBan();
if ($isBlocked) {
$this->errors->set(_t('@users', 'Access is blocked due to:
[reason]', [
'reason' => $isBlocked,
]));
} else {
# проверка доступа в админ-панель
if (! $this->model->userIsAdministrator($userID)) {
$this->errors->accessDenied();
}
}
}
}
if ($this->errors->no('users.admin.login.step2', ['id' => $userID,'data' => &$data])) {
if ($user = Auth::loginUsingId($userID)) {
$user->touchOnLogin();
}
$referer = $this->input->post('ref', TYPE_NOTAGS);
$refererAdmin = Admin::url();
if (
! empty($referer) &&
mb_stripos($referer, $refererAdmin) === 0 &&
$this->security->validateReferer($referer)
) {
return $this->redirect($referer);
}
return $this->redirect($refererAdmin);
}
}
}
return Response::html(
View::template('login', [
'login' => $login,
'errors' => $this->errors->get(true),
])
);
}
/**
* Список пользователей
* @return string|mixed
*/
public function listing()
{
if (! $this->haveAccessTo('members-listing')) {
return $this->showAccessDenied();
}
$mass = [];
$massActions = [
'unblock' => ['t' => _t('@users', 'Unblock'), 'access' => 'users-edit', 'tab' => [3]],
'unfake' => ['t' => _t('@users', 'Convert'), 'access' => 'users-edit', 'tab' => [5]],
'block' => ['t' => _t('@users', 'Block'), 'access' => 'users-edit', 'tab' => [1,2,5], 'params' => ['blocked_reason' => TYPE_STR]],
'delete' => ['t' => _t('@users', 'Delete'), 'access' => 'users-edit', 'tab' => [2,3,5], ],
'del_empty' => ['t' => _t('@users', 'Delete empty accounts'), 'access' => 'users-edit', 'tab' => [5], ],
];
foreach ($massActions as $k => $v) {
if (! $this->haveAccessTo($v['access'])) {
unset($massActions[$k]);
}
}
$action = $this->input->get('act', TYPE_STR);
if ($action) {
$response = [];
switch ($action) {
case 'mass':
$action = $this->input->post('action', TYPE_STR);
if (! isset($massActions[$action])) {
$this->errors->accessDenied();
break;
}
$a = $massActions[$action];
if (isset($a['alias']) && isset($massActions[ $a['alias'] ])) {
$action = $a['alias'];
$a = $massActions[$action];
}
$mass['action'] = $action;
if (isset($a['params'])) {
$params = $this->input->postm($a['params']);
$mass = array_merge($mass, $params);
}
break;
}
if (empty($mass)) {
return $this->ajaxResponseForm($response);
}
}
$f = $this->input->postgetm([
'status' => TYPE_INT, # статус
'q' => TYPE_NOTAGS, # поиск по ID/login/email
'region' => TYPE_UINT, # страна / регион / город
'r_from' => TYPE_NOTAGS, # регистрация: от
'r_to' => TYPE_NOTAGS, # регистрация: до
'a_from' => TYPE_NOTAGS, # авторизация: от
'a_to' => TYPE_NOTAGS, # авторизация: до
'page' => TYPE_UINT, # страница
]);
$filter = [':notSuperAdmin' => 'user_id != 1', 'admin' => 0];
if ($f['status'] > 0) {
switch ($f['status']) {
case 1:
$filter['activated'] = 1;
break;
case 2:
$filter['activated'] = 0;
break;
case 3:
$filter['blocked'] = 1;
break;
case 4:
$filter[':subscribed'] = 'enotify & ' . static::ENOTIFY_NEWS;
$filter['blocked'] = 0;
break;
case 5:
$filter['fake'] = 1;
$filter['blocked'] = 0;
break;
}
}
if ($f['q'] != '') {
$filter[':q'] = [
'( user_id = :q_user_id OR login LIKE :q_login OR email LIKE :q_email OR phone_number LIKE :q_email )',
':q_user_id' => intval($f['q']),
':q_login' => '%' . $f['q'] . '%',
':q_email' => '%' . $f['q'] . '%',
];
}
if ($f['region'] > 0) {
$regionData = Geo::regionData($f['region']);
if (! empty($regionData['numlevel'])) {
$filter['geo_region' . $regionData['numlevel']] = $f['region'];
}
}
# период регистрации
if (! empty($f['r_from'])) {
$r_from = strtotime($f['r_from']);
if (! empty($r_from)) {
$filter[':regFrom'] = ['created >= :regFrom', ':regFrom' => date('Y-m-d', $r_from)];
}
}
if (! empty($f['r_to'])) {
$r_to = strtotime($f['r_to']);
if (! empty($r_to)) {
$filter[':regTo'] = ['created <= :regTo', ':regTo' => date('Y-m-d', $r_to)];
}
}
# период последней авторизации
if (! empty($f['a_from'])) {
$a_from = strtotime($f['a_from']);
if (!empty($a_from)) {
$filter[':authFrom'] = ['last_login >= :authFrom', ':authFrom' => date('Y-m-d', $a_from)];
}
}
if (! empty($f['a_to'])) {
$a_to = strtotime($f['a_to']);
if (!empty($a_to)) {
$filter[':authTo'] = ['last_login <= :authTo', ':authTo' => date('Y-m-d', $a_to)];
}
}
if (! empty($mass)) {
$all = $this->input->post('all', TYPE_BOOL);
$ids = $this->input->post('ids', TYPE_ARRAY_UINT);
if (! $all) {
$filter = ['user_id' => $ids];
}
$count = $this->model->usersList($filter, [], true);
$mass['sql'] = $filter;
if ($count > 100) {
$mass['count'] = $count;
$this->app->cronManager()->executeOnce('users', 'cronAdminMassAction', $mass, md5(json_encode($mass)));
$response = [
'message' => _t('@users', 'The bulk operation is scheduled and will be completed within a few minutes.'),
];
} else {
$response = $this->cronAdminMassAction($mass);
}
return $this->ajaxResponseForm($response);
}
$ordersAllowed = ['user_id' => 'desc', 'email' => 'asc', 'last_login' => 'desc'];
$data = $this->prepareOrder($orderBy, $orderDirection, 'user_id' . tpl::ORDER_SEPARATOR . 'desc', $ordersAllowed);
if (! $f['page']) {
$f['page'] = 1;
}
$data['f'] = $f;
$data['statusNotActivated'] = ($f['status'] == 2);
$data['filter'] = '&' . http_build_query($f);
$total = $this->model->usersList($filter, [], true);
$pages = new Pagination($total, 15, $this->adminLink("listing{$data['filter']}&order=$orderBy-$orderDirection&page=" . Pagination::PAGE_ID));
$data['pgn'] = $pages->view();
$data['total'] = $total;
$data['users'] = $this->model->usersList(
$filter,
[
'user_id','admin','name','login','email','phone_number',
'company_id','last_login','blocked','activated','fake',
],
false,
$pages->getLimitOffset(),
"$orderBy $orderDirection"
);
# данные о компаниях пользователей
if ($data['business_on'] = bff::businessEnabled()) {
$aUsersCompanies = Business::model()->companiesDataToUsersListing((!empty($data['users']) ? array_keys($data['users']) : []));
foreach ($data['users'] as $k => &$v) {
if (isset($aUsersCompanies[$k])) {
$v['company'] = $aUsersCompanies[$k];
}
}
unset($v);
}
$data['list'] = $this->template('admin/listing.ajax', $data);
if ($this->isAJAX()) {
return $this->ajaxResponse([
'list' => $data['list'],
'pgn' => $data['pgn'],
'total' => $data['total'],
]);
}
$data['massActions'] = $massActions;
return $this->template('admin/listing', $data);
}
/**
* Кеширование данных о пользователе
* @param integer $userID
* @return array
*/
public function userData($userID)
{
if (empty($userID)) {
return [];
}
if (! isset($this->cache['user'][$userID])) {
$this->cache['user'][$userID] = $this->model->userData($userID, '*');
}
return $this->cache['user'][$userID];
}
/**
* Список модераторов
* @return string
*/
public function listing_moderators()
{
if (! $this->haveAccessTo('admins-listing')) {
return $this->showAccessDenied();
}
$ordersAllowed = ['user_id' => 'desc', 'login' => 'asc', 'email' => 'asc'];
$data = $this->prepareOrder($orderBy, $orderDirection, 'login' . tpl::ORDER_SEPARATOR . 'asc', $ordersAllowed);
$filter = ['admin' => 1];
$total = $this->model->usersList($filter, [], true);
$pages = new Pagination($total, 20, $this->adminLink(__FUNCTION__ . "&order=$orderBy-$orderDirection&page=" . Pagination::PAGE_ID));
$data['pgn'] = $pages->view();
$data['users'] = $this->model->usersList(
$filter,
['user_id', 'login', 'email', 'password', 'blocked', 'deleted', 'activated'],
false,
$pages->getLimitOffset(),
"$orderBy $orderDirection"
);
# получаем все группы с доступом в админ-панель
$usersGroups = $this->model->usersGroups(true, 'user_id');
foreach ($data['users'] as &$v) {
$v['groups'] = $usersGroups[$v['user_id']] ?? [];
} unset($v);
$data['page'] = $pages->getCurrentPage();
return $this->template('admin/listing.moderators', $data);
}
/**
* Форма добавления пользователя
* @return string|mixed
*/
public function user_add()
{
if (! $this->haveAccessTo('users-edit')) {
return $this->showAccessDenied();
}
$data = [];
$this->validateUserData($data, 0);
if ($this->isPOST()) {
$response = [];
do {
$data['password_salt'] = $this->security->generatePasswordSalt();
$data['password'] = $this->security->passwordHash($data['password'], $data['password_salt']);
$data['activated'] = 1;
if (! empty($data['email'])) {
$data['email_verified'] = 1;
}
if (! empty($data['phone_number'])) {
$data['phone_number_verified'] = 1;
}
$groupsID = $data['group_id'];
unset($data['group_id']);
if (!$this->errors->no('users.admin.user.submit', ['id' => 0, 'data' => &$data, 'groups' => &$groupsID])) {
break;
}
$userID = $this->model->userCreate($data, $groupsID);
if (! $userID) {
$this->errors->impossible();
break;
}
$update = [];
# upload avatar
$avatar = $this->avatar($userID)->uploadFILES('avatar', false, false);
if ($avatar !== false && !empty($avatar['filename'])) {
$update['avatar'] = $avatar['filename'];
}
if (! empty($update)) {
$this->model->userSave($userID, $update);
}
RegisteredEvent::dispatch($userID, ['createdByAdmin' => User::id()]);
$response['redirect'] = ($this->model->userIsAdministrator($userID) ?
'listing_moderators' :
'listing'
);
} while (false);
return $this->iframeResponseForm($response);
}
$data = array_merge($data, ['password' => '', 'password2' => '', 'user_id' => '', 'avatar' => '']);
$this->prepareGroupsOptions($data, [static::GROUPID_SUPERADMIN], [static::GROUPID_MEMBER]);
$data['phones'] = []; # телефоны
$data['user_id'] = 0;
$data['business_on'] = bff::businessEnabled();
$data['region_title'] = '';
return $this->template('admin/user.form', $data);
}
/**
* Форма редактирования пользователя
* @return string|mixed
*/
public function user_edit()
{
if (! $this->haveAccessTo('users-edit')) {
return $this->showAccessDenied();
}
$userID = $this->input->get('rec', TYPE_UINT);
if (! $userID) {
return $this->adminRedirect(Errors::IMPOSSIBLE, 'listing');
}
if ($this->model->userIsAdministrator($userID) && ! $this->haveAccessTo('admins-edit')) {
return $this->showAccessDenied();
}
$data = ['admin' => 0];
# анализируем группы, в которые входит пользователь
$isSuperAdmin = 0;
$userGroups = $this->model->userGroups($userID);
foreach ($userGroups as $v) {
if ($v['group_id'] == static::GROUPID_SUPERADMIN) {
$isSuperAdmin = 1;
}
if ($v['adminpanel'] == 1) {
$data['admin'] = 1;
}
}
if ($this->isPOST()) {
$response = ['reload' => false, 'back' => false];
$this->validateUserData($data, $userID);
if (! $data['admin']) {
# пропускаем настройки предназначенные только для администраторов
unset($data['im_noreply']);
}
do {
# основный данные
$groupsID = $data['group_id'] ?? [];
unset($data['group_id']);
$data['member'] = in_array(static::GROUPID_MEMBER, $groupsID) ? 1 : 0;
if (!$this->errors->no('users.admin.user.submit', ['id' => $userID,'data' => &$data,'groups' => &$groupsID])) {
break;
}
$this->model->userSave($userID, $data);
$update = [];
# аватар
$avatar = $this->avatar($userID)->uploadFILES('avatar', true, false);
if ($avatar !== false && !empty($avatar['filename'])) {
$update['avatar'] = $avatar['filename'];
$response['reload'] = true;
} else {
if ($this->input->postget('avatar_del', TYPE_BOOL)) {
if ($this->avatar($userID)->delete(false)) {
$update['avatar'] = '';
$response['reload'] = true;
}
}
}
# связь с группами
if ($isSuperAdmin && !in_array(static::GROUPID_SUPERADMIN, $groupsID)) {
$groupsID = array_merge($groupsID, [static::GROUPID_SUPERADMIN]);
}
$this->model->userToGroups($userID, $groupsID);
# обновляем, является ли юзер администратором
if ($this->errors->no()) {
$isAdmin = ($this->model->userIsAdministrator($userID) ? 1 : 0);
if ($data['admin'] != $isAdmin) {
$update['admin'] = $isAdmin;
if (! $isAdmin) {
$update['im_noreply'] = 0;
}
}
}
if (! empty($update)) {
$this->model->userSave($userID, $update);
}
if ($this->input->post('back', TYPE_BOOL)) {
$response['back'] = true;
}
} while (false);
return $this->iframeResponseForm($response);
}
$userInfo = $this->model->userData($userID, '*', true);
$data = HTML::escape(array_merge($userInfo, $data), 'html', ['name', 'site']);
$activeGroupsID = [];
for ($j = 0; $j < count($userGroups); $j++) {
$activeGroupsID[] = $userGroups[$j]['group_id'];
}
$this->prepareGroupsOptions($data, ($isSuperAdmin ? null : static::GROUPID_SUPERADMIN), $activeGroupsID);
# настройки компании
$data['business_on'] = bff::businessEnabled();
$data['superadmin'] = $isSuperAdmin;
$data['social'] = $this->social()->getUserSocialAccountsData($userID, true);
$data['admin_auth'] = $this->adminAuthBlock(array_merge($data, $userInfo));
$data['permissionDelete'] = $this->haveAccessTo('users-delete');
if (! empty($data['fake'])) {
$data['unfake_url'] = Admin::url('users/user_action', ['type' => 'unfake', 'rec' => $userID]);
}
return $this->template('admin/user.form', $data);
}
/**
* Обработчик действий в форме редактирования пользователей
* @return \bff\http\Response
*/
public function user_action()
{
if (! $this->haveAccessTo('users-edit')) {
return $this->showAccessDenied();
}
$userID = $this->input->getpost('rec', TYPE_UINT);
if (! $userID) {
return $this->adminRedirect(Errors::IMPOSSIBLE);
}
if ($this->model->userIsSuperAdmin($userID)) {
return $this->adminRedirect(Errors::ACCESSDENIED);
}
if ($this->model->userIsAdministrator($userID) && ! $this->haveAccessTo('admins-edit')) {
return $this->adminRedirect(Errors::ACCESSDENIED);
}
switch ($this->input->get('type')) {
case 'delete': # удаление пользователя
{
# завершение сессии
$this->userSessionDestroy($userID, false); # frontend
if (! User::isCurrent($userID)) {
$this->userSessionDestroy($userID, true); # admin panel
}
$saved = $this->model->userSave($userID, [
'deleted' => static::DESTROY_BY_ADMIN,
'blocked' => 1,
'blocked_reason' => _t('@users', 'User account will be deleted within 24 hours'),
]);
if ($saved) {
$this->app->cronManager()->executeOnce('users', 'cronDeleteUsers');
}
return $this->adminRedirect(Errors::SUCCESS);
}
case 'logout': # завершение сессии
{
$this->userSessionDestroy($userID, false); # frontend
if (! User::isCurrent($userID)) {
$this->userSessionDestroy($userID, true); # admin panel
}
return $this->adminRedirect(Errors::SUCCESS, "user_edit&rec=$userID");
}
case 'unfake': # удаление флага fake
{
$this->userUnfake($userID);
return $this->adminRedirect(Errors::SUCCESS, "user_edit&rec=$userID");
}
}
return $this->adminRedirect(Errors::SUCCESS);
}
/**
* Обработчик ajax действий
* @return \bff\http\Response
*/
public function ajax()
{
$userID = $this->input->getpost('id', TYPE_UINT);
if (! $userID) {
return $this->ajaxResponse(Errors::UNKNOWNRECORD);
}
$action = $this->input->getpost('act', TYPE_STR);
switch ($action) {
case 'user-info': # popup
{
if (! $this->haveAccessTo('members-listing')) {
return $this->showAccessDenied(['popup' => true]);
}
$data = $this->model->userData($userID, '*');
$data['business_on'] = bff::businessEnabled();
if ($data['business_on'] && $data['company_id'] > 0) {
$data['company'] = Business::model()->companyData($data['company_id'], ['title', 'link']);
}
$data['region_title'] = Geo::regionTitle($data['geo_city']);
$data['im_form'] = $this->app->moduleExists('internalmail');
$data['social'] = $this->social()->getUserSocialAccountsData($userID, true);
$data['admin_auth'] = $this->adminAuthBlock(array_merge($data, ['popup' => true]));
return $this->adminModal($data, 'admin/user.info');
}
case 'user-block': # блокировка / разблокировка пользователя
{
if (! $this->haveAccessTo('users-edit')) {
return $this->ajaxResponse(Errors::ACCESSDENIED);
}
if (User::isCurrent($userID)) {
return $this->ajaxResponse(Errors::IMPOSSIBLE);
}
$opt = [
'blocked_reason' => $this->input->postget('blocked_reason', [TYPE_STR, 'len' => 1000]),
'blocked' => $this->input->postget('blocked', TYPE_BOOL),
];
if ($this->userBlock($userID, $opt)) {
return $this->ajaxResponse([
'reason' => nl2br($opt['blocked_reason']),
'blocked' => $opt['blocked'],
]);
}
}
break;
case 'user-activate': # активация пользователя
{
do {
if (! $this->haveAccessTo('users-edit')) {
$this->errors->accessDenied();
break;
}
$data = $this->model->userData($userID, ['user_id', 'activated', 'blocked']);
if (empty($data)) {
$this->errors->impossible();
break;
} else {
if ($data['activated'] == 1) {
$this->errors->set(_t('@users', 'This account is already activated'));
break;
} else {
if ($data['blocked'] == 1) {
$this->errors->set(_t('@users', 'Unable to activate a suspended account'));
break;
}
}
}
if (! $this->userActivate($userID, ['verifyPhone' => true])) {
$this->errors->impossible();
}
} while (false);
return $this->ajaxResponseForm();
}
case 'user-admin-comment': # комментарий о пользователе
{
$response = ['comment' => ''];
do {
if (! $this->haveAccessTo('users-edit')) {
$this->errors->accessDenied();
break;
}
$data = $this->model->userData($userID, ['user_id', 'admin_comment']);
if (empty($data)) {
$this->errors->impossible();
break;
} else {
$response['comment'] = $this->input->post('admin_comment', [TYPE_TEXT, 'len' => 5000]);
$this->model->userSave($userID, [
'admin_comment' => $response['comment'],
]);
}
} while (false);
$response['comment'] = nl2br($response['comment']);
return $this->ajaxResponseForm($response);
}
case 'auth-url':
{
if (! $this->haveAccessTo('users-edit')) {
return $this->showAccessDenied();
}
if ($this->model->userIsAdministrator($userID)) {
return $this->showAccessDenied();
}
$userInfo = $this->model->userData($userID, '*', true);
return $this->ajaxResponseForm([
'url' => $this->adminAuthURL($userInfo['user_id'], $userInfo['last_login'], $userInfo['email'])
]);
}
default:
{
$this->app->hook('users.admin.ajax.default.action', $action, $this);
}
}
return $this->ajaxResponse(Errors::IMPOSSIBLE);
}
/**
* Формирование кнопки для авторизации на фронтенде
* @param array $data
* @return mixed|string
*/
public function adminAuthBlock($data = [])
{
if (! empty($data['admin'])) {
return '';
}
if (empty($data['user_id'])) {
return '';
}
$getData = false;
foreach (['last_login', 'email'] as $f) {
if (empty($data[$f])) {
$getData = true;
break;
}
}
if ($getData) {
$user = $this->model->userData($data['user_id'], ['user_id', 'last_login', 'email']);
if (empty($user['user_id'])) {
return '';
}
$data = array_merge($user, $data);
}
$data['link'] = $this->adminAuthURL($data['user_id'], $data['last_login'], $data['email']);
if (empty($data['link'])) {
return '';
}
return $this->template('admin/admin.auth', $data);
}
/**
* Валидация пользователя
* @param array $data @ref данные
* @param int $userID ID пользователя
* @return void
*/
protected function validateUserData(array &$data, $userID)
{
$params = [
'name' => [TYPE_NOTAGS, 'len' => 50, 'len.sys' => 'users.contacts.name.limit'],
'firstname' => [TYPE_NOTAGS, 'len' => 50, 'len.sys' => 'users.contacts.firstname.limit'],
'surname' => [TYPE_NOTAGS, 'len' => 50, 'len.sys' => 'users.contacts.surname.limit'],
'email' => TYPE_NOTAGS,
'login' => TYPE_NOTAGS,
'geo_city' => TYPE_UINT,
'addr_addr' => [TYPE_NOTAGS, 'len' => 400, 'len.sys' => 'users.form.addr.limit'],
'company_id' => TYPE_UINT, # ID компании
'sex' => TYPE_UINT,
'contacts' => TYPE_ARRAY_NOTAGS,
'phones' => TYPE_ARRAY_NOTAGS,
'site' => TYPE_NOTAGS,
'about' => TYPE_NOTAGS,
'group_id' => TYPE_ARRAY_UINT,
];
$channels = Sendmail::channels();
if (! $this->registerPhone([static::REGISTER_TYPE_PHONE, static::REGISTER_TYPE_BOTH])) {
unset($channels[Sendmail::CHANNEL_SMS]);
}
foreach ($channels as $k => $v) {
$f = 'enotify' . ($k == Sendmail::CHANNEL_EMAIL ? '' : '_' . $k);
$params[$f] = TYPE_ARRAY_UINT;
}
if ($userID) {
$params['changepass'] = TYPE_BOOL;
$params['password'] = TYPE_NOTRIM;
$params['im_noreply'] = TYPE_BOOL;
} else {
$params['password'] = TYPE_NOTRIM;
$params['password2'] = TYPE_NOTRIM;
}
if ($this->registerPhone([static::REGISTER_TYPE_PHONE, static::REGISTER_TYPE_BOTH])) {
$params['phone_number'] = TYPE_NOTAGS;
}
if ($this->profileBirthdate) {
$params['birthdate'] = TYPE_ARRAY_UINT;
}
$this->input->postm($params, $data);
if (! $userID) {
$data['admin'] = 0;
}
if ($this->isPOST()) {
# номер телефона
if ($this->registerPhone([static::REGISTER_TYPE_PHONE, static::REGISTER_TYPE_BOTH]) && (!empty($data['phone_number']) || !$userID)) {
if (! $this->input->isPhoneNumber($data['phone_number'])) {
$this->errors->set(_t('@users', 'Incorrect phone number'), 'phone_number');
}
}
if (! empty($data['phone_number'])) {
if ($this->model->userPhoneExists($data['phone_number'], $userID)) {
$this->errors->set(_t('@users', 'User with specified phone number was already registered'), 'phone_number');
}
}
# email (для авторизации)
if ($this->registerPhone([static::REGISTER_TYPE_EMAIL, static::REGISTER_TYPE_BOTH]) && (!empty($data['email']) || !$userID)) {
if (! $this->input->isEmail($data['email'])) {
$this->errors->set(_t('@users', 'Incorrect email'), 'email');
}
}
if (! empty($data['email'])) {
if ($this->model->userEmailExists($data['email'], $userID)) {
$this->errors->set(_t('@users', 'Email already exists'), 'email');
}
}
# login
if (! $this->isLoginCorrect($data['login'])) {
$this->errors->set(_t('@users', 'Enter a correct login'), 'login');
} elseif ($this->model->userLoginExists($data['login'], $userID)) {
$this->errors->set(_t('@users', 'Login already exists'), 'login');
}
if ($userID) {
if ($data['changepass']) {
if (mb_strlen($data['password']) < $this->passwordMinLength) {
$this->errors->set(_t('@users', 'New password is too short'), 'password');
} else {
$dataCurrent = $this->model->userData($userID, ['password_salt']);
$data['password'] = $this->security->passwordHash($data['password'], $dataCurrent['password_salt']);
}
} else {
unset($data['password']);
}
unset($data['changepass']);
} else {
if (mb_strlen($data['password']) < $this->passwordMinLength) {
$this->errors->set(_t('@users', 'Specified password is too short'), 'password');
} elseif ($data['password'] != $data['password2']) {
$this->errors->set(_t('@users', 'Password confirmation failed'), 'password');
}
unset($data['password2']);
}
# пол
if (!in_array($data['sex'], [static::SEX_MALE, static::SEX_FEMALE])) {
$data['sex'] = static::SEX_MALE;
}
$this->cleanUserData($data);
}
# уведомления
foreach ($channels as $k => $v) {
$f = 'enotify' . ($k == Sendmail::CHANNEL_EMAIL ? '' : '_' . $k);
$data[$f] = array_sum($data[$f]);
}
}
/**
* Подготавливаем options для списков групп
* @param array $data @ref
* @param mixed $exceptGroup
* @param array $activeGroupsID ID активных групп (в которых состоит пользователь)
* @return void
*/
protected function prepareGroupsOptions(array &$data, $exceptGroup, $activeGroupsID = [])
{
$data['active_options'] = '';
$data['exists_options'] = '';
$groupsData = $this->model->groups($exceptGroup, false);
$lang = $this->locale->current();
foreach ($groupsData as $v) {
$option = '';
if (in_array($v['group_id'], $activeGroupsID)) {
$data['active_options'] .= $option;
} else {
$data['exists_options'] .= $option;
}
}
}
}