Вход Регистрация
Файл: system/core/user.php
Строк: 609
<?php

define
('GUEST_GROUP_ID', 1);
define('DEF_GROUP_ID', 3);

class 
cmsUser {

    const 
USER_ONLINE_INTERVAL = 180;
    const 
AUTH_TOKEN_EXPIRATION_INT = 8640000; // 100 дней

    
private static $instance;
    private static 
$_ip;
    public static 
$auth_token;
    private static 
$cached_online = array();

    public 
$id = 0;
    public 
$email;
    public 
$password;
    public 
$nickname;
    public 
$date_log;
    public 
$is_admin   = 0;
    public 
$is_logged  = false;
    public 
$friends    = array();
    public 
$subscribes = array();

    public static function 
getInstance() {
        if (
self::$instance === null) {
            
self::$instance = new self;
        }
        return 
self::$instance;
    }

    public static function 
get($key){
        return 
self::getInstance()->$key;
    }

    public static function 
getIp(){

        if(
self::$_ip === null){

            
$config = cmsConfig::getInstance();

            
self::$_ip = isset($_SERVER[$config->detect_ip_key]) ? $_SERVER[$config->detect_ip_key] : '127.0.0.1';

            if (!
filter_var(self::$_ip, FILTER_VALIDATE_IP)) {
                
self::$_ip = '127.0.0.1';
            }

        }

        return 
self::$_ip;

    }

    public static function 
setIp($ip){
        
self::$_ip = $ip;
    }

    
/**
     * Для var_export
     * @param array $data
     * @return cmsUser
     */
    
public static function __set_state($data) {
        return 
self::getInstance();
    }

    public function 
__construct(){

        
$this->groups   = array(GUEST_GROUP_ID);
        
$this->ip       = self::getIp();
        
$this->date_log = date('Y-m-d H:i:s');

        if (
self::isSessionSet('user:id')){

            
// уже авторизован
            
$this->id = self::sessionGet('user:id');

        } elseif (
self::hasCookie('auth')) {

            
// пробуем авторизовать по кукису
            
$this->id = self::autoLogin(self::getCookie('auth'));

        }

        if(!
$this->id){
            
$this->id = cmsEventsManager::hook('user_auto_login', 0);
        }

        
//
        // если авторизован, заполняем объект данными из базы
        //
        
if ($this->id){
            
$this->loadAuthUser($this->id);
        } else {

            
// для неавторизованных ставим дату посещения
            
$_date_log = self::getCookie('guest_date_log', 'integer');
            if(!
$_date_log){
                
$_date_log = time();
            }

            if (!
self::isSessionSet('user:date_log') || ((time()-self::USER_ONLINE_INTERVAL) >= $_date_log)){

                
self::setCookie('guest_date_log', time(), 31536000);

                if (!
self::isSessionSet('user:date_log')){
                    
self::sessionSet('user:date_log', $_date_log);
                }

            }

            
$this->date_log = date('Y-m-d H:i:s', self::sessionGet('user:date_log'));

        }

    }

    public static function 
restrictSessionToIp($ip = false) {

        if(!
$ip){ $ip = self::getIp(); }

        if (!
self::isSessionSet('user_ip')){

            
self::sessionSet('user_ip', $ip);

            
$octets = explode('.', $ip);
            
$end_okets = end($octets);

            
self::sessionSet('user_net', rtrim($ip, $end_okets));

        }

    }

    
/**
     * Проверяет изменился ли ip адрес сессии
     * @param boolean $strict Если true, то проверяется целый ip адрес, иначе проверка по подсети
     * @return boolean
     */
    
public function checkSpoofingSession($strict = false) {

        if(!
$strict){
            return 
strpos($this->ip, self::sessionGet('user_net')) === 0;
        }

        return 
$this->ip == self::sessionGet('user_ip');

    }

    
/**
     * Загружает данные для авторизованного пользователя
     * @param integer $user_id id пользователя, прошедшего авторизацию
     * @return array
     */
    
public function loadAuthUser($user_id) {

        
$config = cmsConfig::getInstance();
        
$model  = cmsCore::getModel('users');

        
$model->filterIsNull('is_deleted');

        
$user = $model->getUser($user_id);

        if (!
$user){
            
self::logout();
            return array();
        }

        
// если дата последнего визита еще не сохранена в сессии,
        // значит авторизация была только что
        // сохраним дату в сессии и обновим в базе
        
if (!self::isSessionSet('user:date_log') || ((time()-self::USER_ONLINE_INTERVAL) >= strtotime($user['date_log']))){

            if (!
self::isSessionSet('user:date_log')){
                
self::sessionSet('user:date_log', $user['date_log']);
            }

            
$model->updateUserDateLog($user_id);

        }

        
// заполняем объект данными из базы
        
foreach($user as $field=>$value){
            
$this->{$field} = $value;
        }

        
// конвертим список аватаров в массив
        // к пути каждого аватара добавляем путь корня
        
$this->avatar = cmsModel::yamlToArray($this->avatar);
        if (
$this->avatar){
            foreach(
$this->avatar as $size=>$path){
                
$this->avatar[$size] = $config->upload_host . '/' . $path;
            }
        }

        
// кешируем список друзей в сессию
        
$this->recacheFriends();

        
// создаем online-сессию
        
self::createSession($user_id);

        
// восстанавливаем те поля, которые не должны
        // изменяться в течении сессии
        
$this->date_log  = self::sessionGet('user:date_log');
        
$this->perms     = self::getPermissions($user['groups']);
        
$this->is_logged = true;

        return 
cmsEventsManager::hook('user_loaded', $user);

    }

//============================================================================//
//============================================================================//

    
public static function setUserSession($user, $last_ip = false){

        
self::sessionSet('user', array(
            
'id'          => $user['id'],
            
'slug'        => $user['slug'],
            
'2fa'         => !empty($user['2fa']),
            
'is_old_auth' => !empty($user['is_old_auth']),
            
'groups'      => $user['groups'],
            
'time_zone'   => $user['time_zone'],
            
'perms'       => isset($user['permissions']) ? $user['permissions'] : self::getPermissions($user['groups']),
            
'is_admin'    => $user['is_admin']
        ));

        
self::restrictSessionToIp($last_ip);

    }

    
/**
     * Авторизует пользователя по кукису
     * @param str $auth_token
     */
    
public static function autoLogin($auth_token){

        if (!
preg_match('/^[0-9a-z]{128}$/i', $auth_token)){ return 0; }

        
$model = cmsCore::getModel('users');

        
$user = $model->joinInner('{users}_auth_tokens', 'au', 'au.user_id = i.id')->
                
filterEqual('au.auth_token', $auth_token)->filterIsNull('is_deleted')->select('au.date_auth')->getUser();
        if (!
$user || $user['is_locked']){ return 0; }
        
// проверяем не истек ли срок действия токена
        
if((time() - strtotime($user['date_log'])) > self::AUTH_TOKEN_EXPIRATION_INT){
            
$model->deleteAuthToken($auth_token);
            return 
0;
        }
        
// обновляем дату токена
        
$model->filterEqual('auth_token', $auth_token)->updateFiltered('{users}_auth_tokens', array(
            
'date_log' => null
        
));

        
$model->updateUserIp($user['id']);

        
$user = cmsEventsManager::hook('user_login', $user);

        
self::setUserSession($user, $user['ip']);

        return 
intval($user['id']);

    }

    
/**
     * Авторизует пользователя
     *
     * @param string $email
     * @param string $password
     * @param boolean $remember
     * @param boolean $complete_login
     * @return integer|array
     */
    
public static function login($email, $password, $remember = false, $complete_login = true) {

        if (!
$email || !$password){
            return 
0;
        }

        
$model = cmsCore::getModel('users');

        
$user = $model->getUserByAuth($email, $password);

        if(!
$user) {
            
$user = cmsEventsManager::hook('user_auth_error', array('email' => $email, 'password' => $password));
        }

        if (empty(
$user['id'])) { return 0; }

        
$user = cmsEventsManager::hook('user_login', $user);

        
$user['permissions'] = self::getPermissions($user['groups']);

        if(
$complete_login){

            
self::loginComplete($user, $remember);

            return 
intval($user['id']);

        }

        return 
$user;

    }

    
/**
     * Завершает авторизацию, устанавливая сессию
     * и другие параметры авторизации
     *
     * @param array $user
     * @param boolean $remember
     * @return boolean
     */
    
public static function loginComplete($user, $remember = false) {

        
self::setUserSession($user);

        
$model = cmsCore::getModel('users');

        if (
$remember){

            
$auth_token = hash('sha512', string_random(32, $user['email']));

            
self::setCookie('auth', $auth_token, self::AUTH_TOKEN_EXPIRATION_INT);

            
$model->setAuthToken($user['id'], $auth_token);

            
$model->deleteExpiredToken($user['id'], self::AUTH_TOKEN_EXPIRATION_INT);

            
self::$auth_token = $auth_token;

        }

        
$model->updateUserIp($user['id']);

        return 
true;

    }

    
/**
     * Выход пользователя
     */
    
public static function logout() {

        
$model = cmsCore::getModel('users');

        
$userSession = self::sessionGet('user');

        if(!empty(
$userSession['id'])){

            
$model->updateUserDateLog($userSession['id']);

            
$model->filterEqual('user_id', $userSession['id'])->deleteFiltered('sessions_online');

            
cmsEventsManager::hook('user_logout', $userSession);

        }

        if (
self::hasCookie('auth')) {

            
$auth_cookie = self::getCookie('auth');

            if (
preg_match('/^[0-9a-z]{128}$/i', $auth_cookie)){
                
$model->deleteAuthToken($auth_cookie);
            }

            
self::unsetCookie('auth');

        }

        
// если login и logout выполняются в пределах
        // одной загрузки страницы
        
if(self::$auth_token){
            
$model->deleteAuthToken(self::$auth_token);
            
self::$auth_token = null;
        }

        
self::sessionUnset('user');

        
self::getInstance()->id = 0;

        return 
true;
    }

//============================================================================//
//============================================================================//

    
public static function createSession($user_id){

        
$model = new cmsModel();

        
$model->insertOrUpdate('sessions_online', array('user_id' => $user_id), array('date_created' => null));

    }

//============================================================================//
//============================================================================//

    
public static function userIsOnline($user_id) {

        if(isset(
self::$cached_online[$user_id])){
            return 
self::$cached_online[$user_id];
        }

        
self::$cached_online[$user_id] = false;

        
$model = new cmsModel();

        
$date_created = $model->filterEqual('user_id', $user_id)->getFieldFiltered('sessions_online', 'date_created');

        if(
$date_created && (time()-self::USER_ONLINE_INTERVAL) >= strtotime($date_created)){
            
self::$cached_online[$user_id] = true;
        }

        return 
self::$cached_online[$user_id];

    }

    public static function 
isLogged(){
        return 
self::getInstance()->is_logged;
    }

    public static function 
isAdmin() {
        return 
self::getInstance()->is_admin;
    }

    public static function 
goLogin($back_url=''){
        if (!
$back_url){ $back_url = $_SERVER['REQUEST_URI']; }
        
header('Location:' . href_to('auth', 'login') . "?back=" . $back_url);
        exit;
    }

//============================================================================//
//============================================================================//

    
public static function setSessionSavePath($save_handler, $path) {

        if(!
$path){
            return 
false;
        }

        if(
ini_set('session.save_handler', $save_handler) === false){
            return 
false;
        }

        if(
$save_handler === 'files'){

            if(!
is_dir($path)){
                if(!
mkdir($path, 0755, true)){
                    return 
false;
                }
            }

            if (!
is_writable($path)) {
                return 
false;
            }

        }

        
session_save_path($path);

        return 
true;

    }

    public static function 
sessionStart($cookie_domain = false, $session_name = 'ICMSSID'){

        
session_name($session_name);

        if(
$cookie_domain){
            
$cookie_domain = '.'.$cookie_domain;
        }

        
// если используете ТОЛЬКО https, раскомментируйте строку ниже,
        // а следующую за ней закомментируйте
        //session_set_cookie_params(0, '/', $cookie_domain, true, true);
        
session_set_cookie_params(0, '/;SameSite=Lax', $cookie_domain, false, true);

        
session_start();

    }

    public static function 
sessionSet($key, $value){

        if (
strpos($key, ':') === false){
            
$_SESSION[$key] = $value;
        } else {
            list(
$key, $subkey) = explode(':', $key);
            
$_SESSION[$key][$subkey] = $value;
        }

    }

    public static function 
sessionPush($key, $value){
        
$_SESSION[$key][] = $value;
    }

    public static function 
sessionGet($key, $is_clean=false){

        if (!
self::isSessionSet($key)){ return false; }

        if (
strpos($key, ':') === false){
            
$value = $_SESSION[$key];
        } else {
            list(
$key, $subkey) = explode(':', $key);
            
$value = $_SESSION[$key][$subkey];
        }

        if (
$is_clean) { self::sessionUnset($key); }

        return 
$value;

    }

    public static function 
isSessionSet($key){
        if (
strpos($key, ':') === false){
            return isset(
$_SESSION[$key]);
        } else {
            list(
$key, $subkey) = explode(':', $key);
            return isset(
$_SESSION[$key][$subkey]);
        }
    }

    public static function 
sessionUnset($key){
        if (
strpos($key, ':') === false){
            unset(
$_SESSION[$key]);
        } else {
            list(
$key, $subkey) = explode(':', $key);
            unset(
$_SESSION[$key][$subkey]);
        }
    }

    public static function 
sessionClear(){
        
$_SESSION = array();
    }

    
/**
     * Устанавливает куки
     * @param string $key Имя кукиса
     * @param string $value Значение
     * @param int $time Время жизни, в секундах
     * @param string $path Путь на сервере
     * @param bool $http_only Куки недоступны для скриптов
     * @param string $domain Домен действия. null - только текущий
     * */
    
public static function setCookie($key, $value, $time=3600, $path='/', $http_only=true, $domain = null){

        
$cookie_domain = cmsConfig::get('cookie_domain');

        if(!
$domain && $cookie_domain){
            
$domain = $cookie_domain;
        }

        if (
PHP_VERSION_ID < 70300) {
            return 
setcookie('icms['.$key.']', $value, time()+$time, $path, $domain, false, $http_only);
        } else {
            return 
setcookie('icms['.$key.']', $value, [
                
'expires'  => time() + $time,
                
'path'     => $path,
                
'domain'   => $domain,
                
'samesite' => 'Lax',
                
'secure'   => false,
                
'httponly' => $http_only
            
]);
        }
    }

    public static function 
setCookiePublic($key, $value, $time=3600, $path='/'){
        return 
self::setCookie($key, $value, $time, $path, false);
    }

    public static function 
unsetCookie($key, $path='/', $domain = null){
        return 
self::setCookie($key, '', -3600, $path, true, $domain);
    }

    
/**
     * Проверяет наличие кукиса и возвращает его значение
     *
     * @param string $key Имя кукиса
     * @param string $var_type Тип переменной, по умолчанию string
     * @param callable $callback
     * @return mixed
     */
    
public static function getCookie($key, $var_type = 'string', $callback = false){
        if (isset(
$_COOKIE['icms'][$key])){

            
$cookie = $_COOKIE['icms'][$key];

            if(
$var_type !== null){
                @
settype($cookie, $var_type);
            }

            if(
is_callable($callback)){
                
$cookie = call_user_func_array($callback, array($cookie));
            }

            return 
$cookie;

        } else {
            return 
false;
        }
    }

    public static function 
hasCookie($key){
        return isset(
$_COOKIE['icms'][$key]);
    }

//============================================================================//
//============================================================================//

    
public static function getSetUPS($key){
        return 
cmsCore::getModel('users')->getSetUPS($key);
    }

    
/**
     * Устанавливает для пользователя его уникальные персональные настройки
     * User Personal Setting
     *
     * @param str       $key        Ключ настроек
     * @param str|array $data       Данные
     * @param int       $user_id    Ид юзера
     * @return bool
     */
    
public static function setUPS($key, $data, $user_id = null){

        if (empty(
$key) || (!$user_id && !($user_id = self::getInstance()->id))) {
            return 
false;
        }

        return (bool) 
cmsCore::getModel('users')->setUPS($key, $data, $user_id);

    }

    public static function 
getUPS($key, $user_id = null){

        if (empty(
$key) || (!$user_id && !($user_id = self::getInstance()->id))) {
            return 
false;
        }

        return 
cmsCore::getModel('users')->getUPS($key, $user_id);

    }

    public static function 
getUPSActual($key, $data, $user_id = null){

        if (empty(
$key) || (!$user_id && !($user_id = self::getInstance()->id))) {
            return 
false;
        }

        
$umodel = cmsCore::getModel('users');

        
$old = $umodel->getUPS($key, $user_id);
        if (!
$data) {
            return 
$old;
        }
        if (
$old !== $data) {
            
$umodel->setUPS($key, $data, $user_id);
        }

        return 
$data;

    }

    public static function 
deleteUPS($key, $user_id = null){

        if (empty(
$key) || (!$user_id && !($user_id = self::getInstance()->id))) {
            return 
false;
        }

        return 
cmsCore::getModel('users')->deleteUPS($key, $user_id);

    }

    public static function 
deleteUPSlist($key){
        return 
cmsCore::getModel('users')->deleteUPS($key);
    }

//============================================================================//
//============================================================================//

    
public static function addSessionMessage($message, $class = 'info', $is_keep = false){
        
self::sessionPush('core_message', ['class' => $class, 'text' => $message, 'is_keep' => $is_keep]);
    }

    public static function 
getSessionMessages($is_clear = true){

        if (
self::isSessionSet('core_message')){
            
$messages = self::sessionGet('core_message');
        } else {
            
$messages = false;
        }
        if(
$is_clear){
            
self::clearSessionMessages();
        }
        return 
$messages;

    }

    public static function 
clearSessionMessages(){
        
self::sessionUnset('core_message');
    }


//============================================================================//
//============================================================================//

    
public static function getPermissions($groups){

        return 
cmsPermissions::getUserPermissions($groups);

    }

    public static function 
getPermissionValue($subject, $permission){

        
$user = self::getInstance();

        if (!isset(
$user->perms[$subject])) { return false; }
        if (!isset(
$user->perms[$subject][$permission])) { return false; }

        return 
$user->perms[$subject][$permission];

    }

//============================================================================//
//============================================================================//

    
public static function isDenied($subject, $permission, $value=true, $is_admin_strict=false){

        
$user = self::getInstance();

        if(!
$is_admin_strict){
            if (
$user->is_admin){ return false; }
        }

        if (!isset(
$user->perms[$subject])) { return false; }
        if (!isset(
$user->perms[$subject][$permission])) { return false; }

        return 
$user->perms[$subject][$permission] == $value;

    }

    public static function 
isAllowed($subject, $permission, $value=true, $is_admin_strict=false){

        
$user = self::getInstance();

        if(!
$is_admin_strict){
            if (
$user->is_admin){ return true; }
        }

        if (!isset(
$user->perms[$subject])) { return false; }
        if (!isset(
$user->perms[$subject][$permission])) { return false; }
        if (
$user->perms[$subject][$permission] != $value) { return false; }

        return 
true;

    }

    public static function 
isPermittedLimitReached($subject, $permission, $current_value = 0, $is_admin_strict = false) {

        
$user = self::getInstance();

        if(!
$is_admin_strict){
            if (
$user->is_admin){ return false; }
        }

        if (!isset(
$user->perms[$subject])) { return false; }
        if (!isset(
$user->perms[$subject][$permission])) { return false; }
        if ((int)
$current_value >= $user->perms[$subject][$permission]) { return true; }

        return 
false;

    }

    public static function 
isPermittedLimitHigher($subject, $permission, $current_value = 0, $is_admin_strict = false) {

        
$user = self::getInstance();

        if(!
$is_admin_strict){
            if (
$user->is_admin){ return false; }
        }

        if (!isset(
$user->perms[$subject])) { return false; }
        if (!isset(
$user->perms[$subject][$permission])) { return false; }
        if ((int)
$current_value < $user->perms[$subject][$permission]) { return true; }

        return 
false;

    }

//============================================================================//
//============================================================================//

    /**
     * Проверяет членство пользователя в группе
     * @param int $group_id ID группы
     * @return boolean
     */
    
public function isInGroup($group_id){
        return 
in_array($group_id, $this->groups);
    }

    
/**
     * Проверяет членство пользователя в любой группе из списка
     * @param array $groups Список ID групп
     * @return boolean
     */
    
public function isInGroups($groups){

        if (empty(
$groups) || $groups == array(0)){ return true; }
        if (
in_array(0, $groups)){ return true; }

        
$found = false;

        foreach(
$groups as $group_id){
            
$found = $found || in_array($group_id, $this->groups);
        }

        return 
$found;

    }

    public static function 
isUserInGroups($user_groups, $groups){

        if (
in_array(0, $groups)) { return true; }

        
$found = false;

        foreach(
$groups as $group_id){
            
$found = $found || in_array($group_id, $user_groups);
        }

        return 
$found;

    }

//============================================================================//
//============================================================================//

    
public function isPrivacyAllowed($profile, $option, $strict = false){

        if (
$this->is_admin && !$strict) { return true; }

        if (
$profile['id'] == $this->id) { return true; }

        if (!
$profile || !$option) { return false; }

        
$options = $profile['privacy_options'];

        if (!isset(
$options[$option])){ return true; }

        if (
$options[$option] == 'anyone'){ return true; }

        if (
$options[$option] == 'friends' && $this->isFriend($profile['id'])){ return true; }

        return 
false;

    }

//============================================================================//
//============================================================================//

    
public function recacheFriends(){

        
$friends = cmsCore::getModel('users')->getFriendsIds($this->id);

        
$this->friends = $friends['friends'];
        
$this->subscribes = $friends['subscribes'];

        return 
$this;

    }

    public function 
isFriend($friend_id, $type = 'friends'){

        if (!
$friend_id || !$this->id) { return false; }

        if (
$friend_id == $this->id) { return true; }

        if (empty(
$this->{$type})) { return false; }

        return 
in_array($friend_id, $this->{$type});

    }

    public function 
isSubscribe($friend_id){

        return 
$this->isFriend($friend_id, 'subscribes');

    }

    public function 
hasFriends(){
        return !empty(
$this->friends);
    }

    public function 
hasSubscribes(){
        return !empty(
$this->subscribes);
    }

}
Онлайн: 1
Реклама