Пример #1
0
 /**
  * Permission ensuring function, and session keep-alive point.
  * This function should be called on the initialization stage of every page load.
  *
  * CAUTION: When $token is specified, extended security is performed on the current session.
  *          Current session can expire with constant Session::ERR_EXPIRED after 30 minutes of inactivity.
  *
  * @param $token Optional, decided as a one-time key to have advanced security over AJAX calls.
  *        This token string should be get from function requestToken.
  *
  * @return true on access permitted, false otherwise.
  */
 static function ensure($sid, $token = null, $fingerprint = null)
 {
     if (!$sid) {
         return static::ERR_INVALID;
     }
     $res = Node::getOne(array(Node::FIELD_COLLECTION => FRAMEWORK_COLLECTION_SESSION, 'sid' => util::packUuid($sid), 'fingerprint' => $fingerprint));
     if (!$res) {
         return static::ERR_INVALID;
     }
     // One-time token mismatch
     if (($token || $res['token']) && util::packUuid($token) != $res['token']) {
         return false;
     }
     // Session expired
     if (strtotime($res['timestamp']) < strtotime(static::EXPIRE_TIME)) {
         return static::ERR_EXPIRED;
     }
     unset($res['timestamp'], $res['token']);
     // Update timestamp
     Node::set($res);
     static::$currentSession = $res;
     return true;
 }
Пример #2
0
 /**
  * @protected
  *
  * Pack UUID for delete filters.
  */
 function beforeDelete(array &$filter = array())
 {
     if (isset($filter[$this->primaryKey()])) {
         $filter[$this->primaryKey()] = util::packUuid($filter[$this->primaryKey()]);
     }
     return $this;
 }
Пример #3
0
 /**
  * Process next task with POST data.
  */
 public function process()
 {
     // note: Some tasks can work without post data, but request method must be POST.
     if (!$this->__isSuperUser && $this->__request->method() != 'post') {
         $this->__response->status(405);
         // Method not allowed
         return;
     }
     // WorkInstance
     if (!$this->identity()) {
         $this->__response->status(404);
         // WorkInstance not found
         return;
     }
     // TaskInstance
     $instance = $this->nextTask();
     if (!$instance) {
         $this->__response->status(404);
         // TaskInstance not foudn
         return;
     }
     // release mutable lock for work instance initialization.
     $this->_immutable = false;
     // remove tasks to prevent unwanted change.
     $tasks = $this->tasks;
     unset($this->tasks);
     // creates $this->dataStore if not yet.
     if (empty($this->dataStore)) {
         $this->dataStore = array();
     }
     unset($this->lastError);
     // immutable marker to prevent direct modifications to the internal data.
     $this->_immutable = true;
     // note: Send bayeux message to groups with permission to this task.
     $userGroups = $instance->userGroups();
     try {
         // Note: Since $this->dataStore is an array, it is mutable itself.
         $promise = $instance->process();
     } catch (\Exception $e) {
         Log::warning('Task process exception.', array_filter(array('message' => $e->getMessage(), 'code' => $e->getCode(), 'file' => $e->getFile(), 'line' => $e->getLine(), 'trace' => $e->getTrace())));
         $lastError = array('message' => $this->__response->__($e->getMessage()), 'code' => $e->getCode());
         // note: Failure on Headless tasks will revert to previous task.
         if (@$instance->type == 'Headless') {
             $deferred = new Deferred();
             $deferred->reject($lastError['message'], $lastError['code']);
             $promise = $deferred->promise();
             unset($deferred);
         } else {
             $this->_immutable = false;
             $this->lastError = $lastError;
         }
         unset($lastError);
     }
     $this->_immutable = false;
     $result = array();
     $saveFunc = function () use(&$result) {
         unset($this->timestamp);
         $this->save($result);
     };
     if (isset($promise)) {
         // note: rejection here means revert to previous task
         $promise->fail(function ($error, $code = null) use($instance, $tasks) {
             $this->lastError = array_filter(array('message' => $error, 'code' => $code));
             // revert to previous task
             $prevTask = array_search($instance->identity(), array_map(invokes('identity'), $tasks));
             $prevTask = @$tasks[$prevTask - 1];
             // fallback to the first task
             if (!$prevTask) {
                 $prevTask = reset($tasks);
             }
             $this->nextTask = util::packUuid($prevTask->identity());
         });
         // note: resolution always advances to next task
         $promise->done(function () use($instance, $tasks) {
             $nextTask = array_search($instance->identity(), array_map(invokes('identity'), $tasks));
             $nextTask = @$tasks[$nextTask + 1];
             if ($nextTask) {
                 $this->nextTask = util::packUuid($nextTask->identity());
             } else {
                 $this->state = static::STATE_CLOSE;
                 $this->nextTask = null;
             }
         });
         // note: controller script must call resolve() or reject() to make this happen.
         $promise->always($saveFunc);
     } else {
         $saveFunc();
     }
     unset($saveFunc);
     // note: Merge user groups before and after task processing
     if ($this->nextTask) {
         $userGroups = array_unique(array_merge($userGroups, $this->nextTask()->userGroups()));
     }
     foreach ($userGroups as $userGroup) {
         Bayeux::sendMessage("/group/{$userGroup}", array('action' => 'update', '@collection' => 'WorkInstance', 'timestamp' => $this->timestamp));
     }
     if (@$result['error']) {
         $this->__response->status(500);
         return $result;
     } else {
         // note; User might no longer has access to the updated work instance.
         if ($this->data()) {
             $this->__response->status(200);
             return $this;
         } else {
             $this->__response->status(204);
         }
     }
 }