示例#1
0
 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());
 }
示例#2
0
 /**
  * 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;
         }
     }
 }
示例#3
0
	/**
	 * 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());
 }