Example #1
0
 /**
  * This function creates a session and inserts it into the database...
  * The attempt parameter is for use only from within this function for tracking recursion, don't use outside this function.
  * Volatile sessions are sessions which end when the user closes their browser, we can't always tell when the user closes their browser, so we have to limit how long we should assume they are active.
  * Users will opt out of persistent sessions but leave their browser open, if they still don't want to be remembered or they forgot to close it, then we should pretend to have forgot them...
  * We also want to make sure that they are the real user if we haven't heard from them in a while!
  */
 public function create($user_id, $persistent = false, $attempt = 1)
 {
     $now = Carbon::now();
     // set here, avoid multiple function calls
     $expires = $persistent ? Carbon::now()->addDays(self::PERSISTENT_SESSION_DAYS_TO_REMEMBER) : Carbon::now()->addHours(self::VOLATILE_SESSION_ALLOW_HOURS_INACTIVE);
     $id = hash("sha256", microtime());
     // nothing special required, just be unique
     // Create Data Array
     $data = array(':id' => $id, ':user_id' => $user_id, ':update_timestamp' => $now, ':expiry_timestamp' => $expires, ':persistent' => $persistent);
     $db = Database::getConnection();
     $query = $db->query("INSERT INTO " . self::TABLE_NAME . " " . Database::buildSQLInsertQuery($data), $data, ['23505']);
     // Check the Query Result (hopefully no duplicates)
     if ($query && $query->rowCount()) {
         $this->id = $id;
         // update with new ID
         /**
          * Warning: The current cookie variables (if set) contain the old session identifiers and any new SessionModel objects will pick up the old session, not the new one!
          * So, in order for any new SessionModel instantiations to detect our newly created session, we need to update the current session identifiers...
          * By setting the cookie internally to the new session ID, 
          * it means that any functions that look at the current session will see the cookie we're sending out with this request, not the one that came in.
          */
         $_COOKIE[self::COOKIE_NAME] = $id;
         // new ID
         // Set the Cookie
         setcookie(self::COOKIE_NAME, $id, $persistent ? $expires->timestamp : 0, '/', COOKIE_DOMAIN, RequestModel::currentRequest()->isHTTPS(), true);
         return true;
     } else {
         if ($query && $query->errorCode() == "23505") {
             // 23505 = duplicate key (hash)
             // Attempt to generate a key 3 times only!
             if ($attempt < 3) {
                 // Attempt Again...
                 $this->create($user_id, $persistent, ++$attempt);
             } else {
                 // We've used up all the recursion attempts, shouldn't have -- would be a pretty rare occurance! (another error somewhere?)
                 // The collision probability is miniscule, but requests of the same microtime() will yield a collision, let's just plan for it...
                 AppController::fatalError('All recursive attempts at generating a session ID have failed due to duplicate keys!');
             }
         }
     }
 }
Example #2
0
 public function save($idInsert = false)
 {
     $this->modelFields = array_unique($this->modelFields);
     // remove duplicates
     if (isset($this->{$this->idField}) && !$idInsert) {
         // UPDATE
         foreach ($this->modelFields as $field) {
             $data[":{$field}"] = is_string($this->{$field}) ? trim($this->{$field}) : $this->{$field};
         }
         $sql = "UPDATE {$this->tableName} SET " . Database::buildSQLUpdateQuery($data) . " WHERE {$this->idField}=:{$this->idField} RETURNING {$this->idField}";
     } else {
         // Add ID Field?
         if ($idInsert) {
             $data[":{$this->idField}"] = $this->{$this->idField};
         }
         // INSERT
         foreach ($this->modelFields as $field) {
             if ($field != $this->idField) {
                 $data[":{$field}"] = is_string($this->{$field}) ? trim($this->{$field}) : $this->{$field};
             }
         }
         $sql = "INSERT INTO {$this->tableName} " . Database::buildSQLInsertQuery($data) . " RETURNING {$this->idField}";
     }
     $db = Database::getConnection();
     $query = $db->query($sql, $data);
     // We need to fetch a clean copy following a save...
     return $query && $query->rowCount() ? self::find($query->fetchColumn(0)) : false;
 }