public function execute() { $view = $this->getView(); $fac = new ModelFactory('PageModel'); $fac->where('baseurl LIKE /blog/view/%'); $fac->where('published_status = published'); $fac->where('published <= ' . \Core\Date\DateTime::NowGMT()); $fac->limit($this->getSetting('count')); switch ($this->getSetting('sort')) { case 'newest': $fac->order('published DESC'); break; case 'popular': $fac->order('popularity DESC'); break; case 'random': $fac->order('RAND()'); break; } if (!$fac->count()) { // If there are no results found, then do not display the widget. return ''; } $view->assign('sort', $this->getSetting('sort')); $view->assign('title', $this->getSetting('title')); $view->assign('links', $fac->get()); }
/** * The hook catch for the "/core/admin/view" hook. */ public static function AdminHook() { // If this user doesn't have access to manage crons, just continue. if (!\Core\user()->checkAccess('p:/cron/viewlog')) { return; } $suffixtext = 'This could be a problem if you have scripts relying on it! <a href="' . \Core\resolve_link('/cron/howto') . '">Read how to resolve this issue</a>.'; // Lookup and make sure that the cron hooks have ran recently enough! $checks = [['cron' => 'hourly', 'modify' => '-1 hour', 'label' => 'hour'], ['cron' => 'daily', 'modify' => '-1 day', 'label' => 'day'], ['cron' => 'weekly', 'modify' => '-1 week', 'label' => 'week'], ['cron' => 'monthly', 'modify' => '-1 month', 'label' => 'month']]; foreach ($checks as $check) { $time = new CoreDateTime(); $cronfac = new ModelFactory('CronLogModel'); $cronfac->where('cron = ' . $check['cron']); $time->modify($check['modify']); $cronfac->where('created >= ' . $time->getFormatted('U', Time::TIMEZONE_GMT)); $count = $cronfac->count(); if ($count == 0) { \Core\set_message('Your ' . $check['cron'] . ' cron has not run in the last ' . $check['label'] . '! ' . $suffixtext, 'error'); // Only complain to the admin once per view. return; } } }
/** * Get a count of records that match a given where criteria * * @static * * @param array $where * * @return int */ public static function Count($where = []) { $fac = new ModelFactory(get_called_class()); $fac->where($where); return $fac->count(); }
/** * Given all the user defined filter, sort, and what not, apply those values to the ModelFactory if possible. * * @since 2.4.0 * @param ModelFactory $factory */ public function applyToFactory(ModelFactory $factory){ if($this->hassort){ $factory->order($this->getOrder()); } if($this->haspagination){ // Determine the starting count if the page is requested. if($this->_currentpage > 1){ $startat = $this->_limit * ($this->_currentpage - 1); $factory->limit($startat . ', ' . $this->_limit); } else{ $factory->limit($this->_limit); } } foreach($this->_elements as $el){ /** @var $el FormElement */ $name = $el->get('name'); $idxname = $name; if(strpos($name, 'filter[') === 0){ $name = substr($name, 7, -1); } // If this element is not in the index of elements, skip to the next element. if(!isset($this->_elementindexes[$idxname])){ continue; } // If this doesn't have a link attribute, just skip. if(!$el->get('link')){ continue; } // No value, just skip. if($el->get('value') === '' || $el->get('value') === null){ continue; } // If there is a "" option, interpret that as empty and allow "0" to be used. if($el->get('value') === '0'){ if($el->get('options') && isset($el->get('options')[''])){ // '' is set... proceed. } else{ continue; } } $value = $el->get('value'); // Was there a prefix and/or suffix requested? if($el->get('linkvalueprefix')){ $value = $el->get('linkvalueprefix') . $value; } if($el->get('linkvaluesuffix')){ $value = $value . $el->get('linkvaluesuffix'); } // If this link is a date object, convert a date string to its unix timestamp representation. if($el instanceof FormDateInput || $el->get('dateformat')){ // Default to a unix timestamp, but allow the user to override this. // This is useful for saving a date in the datastore as a human-readable format. $format = $el->get('dateformat') ? $el->get('dateformat') : 'U'; $date = new CoreDateTime($value); $value = $date->getFormatted($format, Time::TIMEZONE_GMT); } if($el->get('linkname')){ $name = $el->get('linkname'); } // New support for multiple link names! if(!is_array($name)){ $name = [$name]; } $statements = []; foreach($name as $n){ switch($el->get('link')){ case FilterForm::LINK_TYPE_STANDARD: case FilterForm::LINK_TYPE_GT: case FilterForm::LINK_TYPE_GE: case FilterForm::LINK_TYPE_LT: case FilterForm::LINK_TYPE_LE: $statements[] = $n . $el->get('link') . $value; break; case FilterForm::LINK_TYPE_STARTSWITH: $statements[] = $n . ' LIKE ' . $value . '%'; break; case FilterForm::LINK_TYPE_CONTAINS: $statements[] = $n . ' LIKE %' . $value . '%'; break; } } if(sizeof($statements) > 1){ // Create a sub where clause for these. $subwhere = new \Core\Datamodel\DatasetWhereClause(); $subwhere->setSeparator('OR'); foreach($statements as $s){ $subwhere->addWhere($s); } // Add this sub clause to the main where clause. $factory->where($subwhere); } else{ // A single command just gets added to the main clause. $factory->where($statements[0]); } } // Might as well update the count now, it can always be updated later. $this->setTotalCount($factory->count()); }
/** * Method to cleanup expired IP addresses from the database. * * @return bool */ public static function CleanupHook() { $factory = new \ModelFactory('IpBlacklistModel'); $factory->where('expires > 0'); // If they're set not to be deleted, don't purge them... $factory->where('expires <= ' . \CoreDateTime::Now('U', \Time::TIMEZONE_GMT)); // DELETE! $count = $factory->count(); if (!$count) { echo 'No records purged.'; return true; } foreach ($factory->get() as $record) { /** @var $record \IpBlacklistModel */ $record->delete(); } echo "Purged " . $count . ' record' . ($count > 1 ? 's' : '') . ' successfully.'; return true; }
/** * Form Handler for logging in. * * @static * * @param \Form $form * * @return bool|null|string */ public static function LoginHandler(\Form $form){ /** @var \FormElement $e */ $e = $form->getElement('email'); /** @var \FormElement $p */ $p = $form->getElement('pass'); /** @var \UserModel $u */ $u = \UserModel::Find(array('email' => $e->get('value')), 1); if(!$u){ // Log this as a login attempt! $logmsg = 'Failed Login. Email not registered' . "\n" . 'Email: ' . $e->get('value') . "\n"; \SystemLogModel::LogSecurityEvent('/user/login', $logmsg); $e->setError('t:MESSAGE_ERROR_USER_LOGIN_EMAIL_NOT_FOUND'); return false; } if($u->get('active') == 0){ // The model provides a quick cut-off for active/inactive users. // This is the control managed with in the admin. $logmsg = 'Failed Login. User tried to login before account activation' . "\n" . 'User: '******'email') . "\n"; \SystemLogModel::LogSecurityEvent('/user/login', $logmsg, null, $u->get('id')); $e->setError('t:MESSAGE_ERROR_USER_LOGIN_ACCOUNT_NOT_ACTIVE'); return false; } elseif($u->get('active') == -1){ // The model provides a quick cut-off for active/inactive users. // This is the control managed with in the admin. $logmsg = 'Failed Login. User tried to login after account deactivation.' . "\n" . 'User: '******'email') . "\n"; \SystemLogModel::LogSecurityEvent('/user/login', $logmsg, null, $u->get('id')); $e->setError('t:MESSAGE_ERROR_USER_LOGIN_ACCOUNT_DEACTIVATED'); return false; } try{ /** @var \Core\User\AuthDrivers\datastore $auth */ $auth = $u->getAuthDriver('datastore'); } catch(Exception $e){ $e->setError('t:MESSAGE_ERROR_USER_LOGIN_PASSWORD_AUTH_DISABLED'); return false; } // This is a special case if the password isn't set yet. // It can happen with imported users or if a password is invalidated. if($u->get('password') == ''){ // Use the Nonce system to generate a one-time key with this user's data. $nonce = \NonceModel::Generate( '20 minutes', ['type' => 'password-reset', 'user' => $u->get('id')] ); $link = '/datastoreauth/forgotpassword?e=' . urlencode($u->get('email')) . '&n=' . $nonce; $email = new \Email(); $email->setSubject('Initial Password Request'); $email->to($u->get('email')); $email->assign('link', \Core\resolve_link($link)); $email->assign('ip', REMOTE_IP); $email->templatename = 'emails/user/initialpassword.tpl'; try{ $email->send(); \SystemLogModel::LogSecurityEvent('/user/initialpassword/send', 'Initial password request sent successfully', null, $u->get('id')); \Core\set_message('t:MESSAGE_INFO_USER_LOGIN_MUST_SET_NEW_PASSWORD_INSTRUCTIONS_HAVE_BEEN_EMAILED'); return true; } catch(\Exception $e){ \Core\ErrorManagement\exception_handler($e); \Core\set_message('t:MESSAGE_ERROR_USER_LOGIN_MUST_SET_NEW_PASSWORD_UNABLE_TO_SEND_EMAIL'); return false; } } if(!$auth->checkPassword($p->get('value'))){ // Log this as a login attempt! $logmsg = 'Failed Login. Invalid password' . "\n" . 'Email: ' . $e->get('value') . "\n"; \SystemLogModel::LogSecurityEvent('/user/login/failed_password', $logmsg, null, $u->get('id')); // Also, I want to look up and see how many login attempts there have been in the past couple minutes. // If there are too many, I need to start slowing the attempts. $time = new \CoreDateTime(); $time->modify('-5 minutes'); $securityfactory = new \ModelFactory('SystemLogModel'); $securityfactory->where('code = /user/login/failed_password'); $securityfactory->where('datetime > ' . $time->getFormatted(\Time::FORMAT_EPOCH, \Time::TIMEZONE_GMT)); $securityfactory->where('ip_addr = ' . REMOTE_IP); $attempts = $securityfactory->count(); if($attempts > 4){ // Start slowing down the response. This should help deter brute force attempts. // (x+((x-7)/4)^3)-4 sleep( ($attempts+(($attempts-7)/4)^3)-4 ); // This makes a nice little curve with the following delays: // 5th attempt: 0.85 // 6th attempt: 2.05 // 7th attempt: 3.02 // 8th attempt: 4.05 // 9th attempt: 5.15 // 10th attempt: 6.52 // 11th attempt: 8.10 // 12th attempt: 10.05 } $e->setError('t:MESSAGE_ERROR_USER_LOGIN_INCORRECT_PASSWORD'); $p->set('value', ''); return false; } if($form->getElementValue('redirect')){ // The page was set via client-side javascript on the login page. // This is the most reliable option. $url = $form->getElementValue('redirect'); } elseif(REL_REQUEST_PATH == '/user/login'){ // If the user came from the registration page, get the page before that. $url = $form->referrer; } else{ // else the registration link is now on the same page as the 403 handler. $url = REL_REQUEST_PATH; } // Well, record this too! \SystemLogModel::LogSecurityEvent('/user/login', 'Login successful (via password)', null, $u->get('id')); // yay... $u->set('last_login', \CoreDateTime::Now('U', \Time::TIMEZONE_GMT)); $u->save(); \Core\Session::SetUser($u); // Allow an external script to override the redirecting URL. $overrideurl = \HookHandler::DispatchHook('/user/postlogin/getredirecturl'); if($overrideurl){ $url = $overrideurl; } return $url; }
public function execute() { $view = $this->getView(); $fac = new ModelFactory('PageModel'); if ($this->getSetting('blog')) { $fac->where('parenturl = /blog/view/' . $this->getSetting('blog')); } $fac->where('parenturl LIKE /blog/view/%'); $fac->where('published_status = published'); $fac->where('published <= ' . \Core\Date\DateTime::NowGMT()); $fac->limit($this->getSetting('count')); switch ($this->getSetting('sort')) { case 'newest': $fac->order('published DESC'); break; case 'popular': $fac->order('popularity DESC'); break; case 'random': $fac->order('RAND()'); break; } if (!$fac->count()) { // If there are no results found, then do not display the widget. return ''; } $view->assign('count', $this->getSetting('count')); $view->assign('sort', $this->getSetting('sort')); $view->assign('title', $this->getSetting('title')); // The template is expecting an array, if count is 1, only a single Model is returned from the factory. $view->assign('links', $this->getSetting('count') == 1 ? [$fac->get()] : $fac->get()); }