/** * Get all user sessions * * @param int $roleId * @param array $search * @param int $limit * @param int $page * @param string $sort * @return array */ public function getAll($roleId = null, array $search = null, $limit = null, $page = null, $sort = null) { $sql = Table\UserSessions::sql(); $sql->select(['id' => DB_PREFIX . 'user_sessions.id', 'user_id' => DB_PREFIX . 'user_sessions.user_id', 'ip' => DB_PREFIX . 'user_sessions.ip', 'ua' => DB_PREFIX . 'user_sessions.ua', 'start' => DB_PREFIX . 'user_sessions.start', 'user_role_id' => DB_PREFIX . 'users.role_id', 'username' => DB_PREFIX . 'users.username', 'first_name' => DB_PREFIX . 'users.first_name', 'last_name' => DB_PREFIX . 'users.last_name', 'company' => DB_PREFIX . 'users.company', 'title' => DB_PREFIX . 'users.title', 'email' => DB_PREFIX . 'users.email', 'active' => DB_PREFIX . 'users.active', 'verified' => DB_PREFIX . 'users.verified', 'role_id' => DB_PREFIX . 'roles.id', 'role_name' => DB_PREFIX . 'roles.name'])->join(DB_PREFIX . 'users', [DB_PREFIX . 'users.id' => DB_PREFIX . 'user_sessions.user_id'])->join(DB_PREFIX . 'roles', [DB_PREFIX . 'users.role_id' => DB_PREFIX . 'roles.id']); if (null !== $limit) { $page = null !== $page && (int) $page > 1 ? $page * $limit - $limit : null; $sql->select()->offset($page)->limit($limit); } $params = []; $order = $this->getSortOrder($sort, $page); $by = explode(' ', $order); $sql->select()->orderBy($by[0], $by[1]); if (null !== $search) { $sql->select()->where($search['by'] . ' LIKE :' . $search['by']); $params[$search['by']] = $search['for'] . '%'; } if (null !== $roleId) { if ($roleId == 0) { $sql->select()->where(DB_PREFIX . 'users.role_id IS NULL'); $rows = count($params) > 0 ? Table\UserSessions::execute((string) $sql, $params)->rows() : Table\UserSessions::query((string) $sql)->rows(); } else { $sql->select()->where(DB_PREFIX . 'users.role_id = :role_id'); $params['role_id'] = $roleId; $rows = Table\UserSessions::execute((string) $sql, $params)->rows(); } } else { $rows = count($params) > 0 ? Table\UserSessions::execute((string) $sql, $params)->rows() : Table\UserSessions::query((string) $sql)->rows(); } return $rows; }
/** * Login and track session * * @param AbstractController $controller * @param Application $application * @return void */ public static function login(AbstractController $controller, Application $application) { $sess = $application->getService('session'); $userUri = APP_URI; $key = 'user'; if (isset($sess->member) && $application->isRegistered('phire-members')) { $key = 'member'; $memberAdmin = new \Phire\Members\Model\MembersAdmin(); $memberAdmin->getByRoleId($sess->member->role_id); if (isset($memberAdmin->uri)) { $userUri = $memberAdmin->uri; } } $path = BASE_PATH . $userUri; if ($path == '') { $path = '/'; } $cookie = Cookie::getInstance(['path' => $path]); $cookie->delete('phire_session_timeout'); $cookie->delete('phire_session_path'); // If login, validate and start new session if ($controller->request()->isPost() && substr($controller->request()->getRequestUri(), -6) == '/login') { // If the user successfully logged in if (isset($sess[$key])) { $config = Table\UserSessionConfig::findById($sess[$key]->role_id); $data = Table\UserSessionData::findById($sess[$key]->id); if (isset($config->role_id)) { if (!self::validate($config, $sess[$key], $data)) { if (isset($data->user_id)) { $data->failed_attempts++; $data->save(); } else { $data = new Table\UserSessionData(['user_id' => $sess[$key]->id, 'logins' => null, 'failed_attempts' => 1]); $data->save(); } if (isset($config->role_id) && (int) $config->log_type > 0 && null !== $config->log_emails) { self::log($config, $sess[$key], false); } $sess->kill(); Response::redirect(BASE_PATH . $userUri . '/login?failed=' . $data->failed_attempts); exit; } else { if (isset($data->user_id)) { $limit = (int) $application->module('phire-sessions')['login_limit']; $logins = unserialize($data->logins); if ($limit > 0 && count($logins) >= $limit) { reset($logins); unset($logins[key($logins)]); } $logins[time()] = ['ua' => $_SERVER['HTTP_USER_AGENT'], 'ip' => $_SERVER['REMOTE_ADDR']]; $data->total_logins++; $data->failed_attempts = 0; $data->logins = serialize($logins); $data->save(); } else { $data = new Table\UserSessionData(['user_id' => $sess[$key]->id, 'logins' => serialize([time() => ['ua' => $_SERVER['HTTP_USER_AGENT'], 'ip' => $_SERVER['REMOTE_ADDR']]]), 'total_logins' => 1, 'failed_attempts' => 0]); $data->save(); } } $expire = (int) $config->session_expiration > 0 ? (int) $config->session_expiration : null; $timeout = (int) $config->timeout_warning; } else { $expire = null; $timeout = false; } $lastLogin = null; $lastIp = null; // Check for the last login $data = Table\UserSessionData::findById($sess[$key]->id); if (isset($data->user_id)) { $logins = null !== $data->logins ? unserialize($data->logins) : []; if (count($logins) > 1) { $keys = array_keys($logins); $timestamp = isset($keys[count($keys) - 2]) ? $keys[count($keys) - 2] : null; if (null !== $timestamp && isset($logins[$timestamp])) { $lastLogin = $timestamp; $lastIp = $logins[$timestamp]['ip']; } } } // Clear old sessions $clear = (int) $application->module('phire-sessions')['clear_sessions']; if ($clear > 0) { $clear = time() - $clear; $sql = Table\UserSessions::sql(); $sql->delete()->where(['start <= :start']); Table\UserSessions::execute((string) $sql, ['start' => $clear]); } $session = new Table\UserSessions(['user_id' => $sess[$key]->id, 'ip' => $_SERVER['REMOTE_ADDR'], 'ua' => $_SERVER['HTTP_USER_AGENT'], 'start' => time()]); $session->save(); $sess[$key]->session = new \ArrayObject(['id' => $session->id, 'start' => $session->start, 'last' => $session->start, 'expire' => $expire, 'timeout' => $timeout, 'last_login' => $lastLogin, 'last_ip' => $lastIp], \ArrayObject::ARRAY_AS_PROPS); if (isset($config->role_id) && (int) $config->log_type > 0 && null !== $config->log_emails) { self::log($config, $sess[$key], true); } // Else, if the user login failed } else { if (null !== $controller->view()->form && $controller->view()->form !== false && null !== $controller->view()->form->username) { $user = \Phire\Table\Users::findBy(['username' => $controller->view()->form->username]); $config = Table\UserSessionConfig::findById($user->role_id); if (isset($user->id)) { $data = Table\UserSessionData::findById($user->id); if (isset($data->user_id)) { $data->failed_attempts++; $data->save(); } else { $data = new Table\UserSessionData(['user_id' => $user->id, 'logins' => null, 'failed_attempts' => 1]); $data->save(); } if (isset($config->role_id) && (int) $config->log_type > 0 && null !== $config->log_emails) { self::log($config, $user, false); } } } } // Check existing session } else { if (isset($sess[$key]) && isset($sess[$key]->session)) { if (!isset(Table\UserSessions::findById((int) $sess[$key]->session->id)->id) || null !== $sess[$key]->session->expire && time() - $sess[$key]->session->last >= $sess[$key]->session->expire) { $session = Table\UserSessions::findById((int) $sess[$key]->session->id); if (isset($session->id)) { $session->delete(); } $sess->kill(); Response::redirect(BASE_PATH . $userUri . '/login?expired=1'); exit; } else { if ($sess[$key]->session->timeout && null !== $sess[$key]->session->expire) { $cookie->set('phire_session_timeout', $sess[$key]->session->expire - 30); $cookie->set('phire_session_path', BASE_PATH . $userUri); } $sess[$key]->session->last = time(); } } } }