/**
  * Add authorization check before calling any action
  *
  * @return
  *   a HTTP status code. This method add only authorization checks
  *   so it can return No2_HTTP::UNAUTHORIZED, No2_HTTP::FORBIDDEN or
  *   No2_HTTP::OK.
  */
 protected function before_filter()
 {
     // csrf check
     $csrf_methods = ['POST', 'PUT', 'PATCH', 'DELETE'];
     if ($this->check_csrf() && in_array($this->http_method, $csrf_methods)) {
         $req_http_headers = array_change_key_case(getallheaders(), CASE_LOWER);
         if (array_key_exists('x-csrf-token', $req_http_headers)) {
             $token = $req_http_headers['x-csrf-token'];
         } else {
             if (array_key_exists('_csrf', $_REQUEST)) {
                 $token = $_REQUEST['_csrf'];
             } else {
                 $token = "";
             }
         }
         if (!csrf_token_check($token)) {
             No2_Logger::warn(sprintf('bad CSRF token: expected [%s] but got [%s]', csrf_token(), $token));
             return No2_HTTP::BAD_REQUEST;
         }
     }
     // authorization check
     if (!$this->authorize(current_user(), $this->action)) {
         return current_user()->is_anonymous() ? No2_HTTP::UNAUTHORIZED : No2_HTTP::FORBIDDEN;
     }
     return parent::before_filter();
 }
Пример #2
0
 /**
  * find the associated controller to $alias.
  *
  * @param $alias
  *   the alias to find a matching controller
  *
  * @param $action
  *   The action (method) to perform. It will be passed to the respond_to()
  *   method of the controller in order to check if it can handle it.
  *
  * @param $http_method
  *   The HTTP verb, usually GET or POST.
  *
  * @return
  *   a controller object that can handle $action. If there isn't any, null is
  *   returned.
  */
 public function find_route($alias, $action, $http_method)
 {
     if (!array_key_exists($alias, $this->mapping)) {
         return null;
     }
     $target = $this->mapping[$alias];
     /* require the associated file if any */
     if (!is_null($target['file'])) {
         require_once $target['file'];
     }
     // check if the controller responding to $alias can handle $action
     $klass = $target['controller'];
     try {
         $controller = new $klass($alias, $action, $http_method);
     } catch (Exception $e) {
         No2_Logger::warn(get_class($this) . '::find_route: ' . 'exception in controller ctor: ' . $e->getMessage());
         return null;
     }
     return $controller;
 }
Пример #3
0
 /**
  * update this model's properties.
  *
  * This method fiter some properties given in order to avoid user injection
  * of internal data field like id. The internal_fields() function can setup
  * an array of fields that should be filtered.
  *
  * @param $properties
  *   An array of new properties.
  */
 public function update_properties($properties)
 {
     $db_infos = $this->db_infos();
     $reflect = new ReflectionClass($this);
     foreach ($properties as $name => $val) {
         /*
          * first try to set $name as a db field. It is expected to match
          * most of the time so it would be costly to test the property
          * reflection first (which would be throw happy).
          */
         if (array_key_exists($name, $db_infos)) {
             $field_infos = $db_infos[$name];
             // filter out protected properties.
             if (array_key_exists('protected', $field_infos) && $field_infos['protected']) {
                 No2_Logger::warn(get_class($this) . '#update_properties: ' . "filtering out {$field} (protected)");
             } else {
                 $this->{$name} = $val;
                 // see __set()
             }
         } else {
             $p = $reflect->getProperty($name);
             if ($p->isPublic() && !$p->isStatic()) {
                 $p->setValue($this, $val);
             } else {
                 $msg = 'Undefined property ' . get_class($this) . "::\${$name}";
                 throw new InvalidArgumentException($msg);
             }
         }
     }
 }
 /**
  * execute an UPDATE instruction. set() should have been called before.
  *
  * @return
  *   false on error, true otherwise.
  */
 public function update()
 {
     $this->restrict_to(self::UPDATE);
     if (empty($this->set)) {
         No2_Logger::warn(get_class($this) . '::update: ' . 'called without previous set() call.');
     }
     $klass = $this->klass;
     $arguments = array_merge($this->arguments, ['{__table}' => $klass::$table]);
     $options = ['profile' => $this->profile];
     $db = static::_database_or_throw($this->profile);
     $updated = false;
     if ($db->has_returning()) {
         $sql = "UPDATE {__table} {$this->set} {$this->where} RETURNING *";
         $updated = static::execute($sql, $arguments, $options);
     } else {
         // XXX: asume MySQL, hacky.
         $last_insert_id_hack = (empty($this->set) ? 'SET' : ',') . ' id = LAST_INSERT_ID(id)';
         $sql = "UPDATE {__table} {$this->set} {$last_insert_id_hack} {$this->where}";
         if (static::execute($sql, $arguments, $options) !== false) {
             $updated = static::execute('SELECT * FROM {__table} WHERE id = LAST_INSERT_ID()', $arguments, $options);
         }
     }
     if ($updated !== false) {
         return $updated;
     } else {
         No2_Logger::warn(get_class($this) . '::update: ' . "SQL query returned FALSE: {$sql}");
         No2_Logger::warn('error message: ' . $db->error());
         return null;
     }
 }