Page MenuHomePhabricator

D7976.id18048.diff
No OneTemporary

D7976.id18048.diff

Index: resources/sql/autopatches/20140115.auth.2.expires.sql
===================================================================
--- /dev/null
+++ resources/sql/autopatches/20140115.auth.2.expires.sql
@@ -0,0 +1,8 @@
+ALTER TABLE {$NAMESPACE}_user.phabricator_session
+ ADD sessionExpires INT UNSIGNED NOT NULL;
+
+UPDATE {$NAMESPACE}_user.phabricator_session
+ SET sessionExpires = UNIX_TIMESTAMP() + (60 * 60 * 24 * 30);
+
+ALTER TABLE {$NAMESPACE}_user.phabricator_session
+ ADD KEY `key_expires` (sessionExpires);
Index: src/__phutil_library_map__.php
===================================================================
--- src/__phutil_library_map__.php
+++ src/__phutil_library_map__.php
@@ -1211,6 +1211,7 @@
'PhabricatorAuthRegisterController' => 'applications/auth/controller/PhabricatorAuthRegisterController.php',
'PhabricatorAuthSession' => 'applications/auth/storage/PhabricatorAuthSession.php',
'PhabricatorAuthSessionEngine' => 'applications/auth/engine/PhabricatorAuthSessionEngine.php',
+ 'PhabricatorAuthSessionGarbageCollector' => 'applications/auth/garbagecollector/PhabricatorAuthSessionGarbageCollector.php',
'PhabricatorAuthSessionQuery' => 'applications/auth/query/PhabricatorAuthSessionQuery.php',
'PhabricatorAuthStartController' => 'applications/auth/controller/PhabricatorAuthStartController.php',
'PhabricatorAuthUnlinkController' => 'applications/auth/controller/PhabricatorAuthUnlinkController.php',
@@ -3791,6 +3792,7 @@
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorAuthSessionEngine' => 'Phobject',
+ 'PhabricatorAuthSessionGarbageCollector' => 'PhabricatorGarbageCollector',
'PhabricatorAuthSessionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorAuthStartController' => 'PhabricatorAuthController',
'PhabricatorAuthUnlinkController' => 'PhabricatorAuthController',
Index: src/applications/auth/engine/PhabricatorAuthSessionEngine.php
===================================================================
--- src/applications/auth/engine/PhabricatorAuthSessionEngine.php
+++ src/applications/auth/engine/PhabricatorAuthSessionEngine.php
@@ -5,11 +5,15 @@
public function loadUserForSession($session_type, $session_key) {
$session_table = new PhabricatorAuthSession();
$user_table = new PhabricatorUser();
- $conn_r = $session_table->establishConnection('w');
+ $conn_r = $session_table->establishConnection('r');
+
+ // NOTE: We're being clever here because this happens on every page load,
+ // and by joining we can save a query.
$info = queryfx_one(
$conn_r,
- 'SELECT u.* FROM %T u JOIN %T s ON u.phid = s.userPHID
+ 'SELECT s.sessionExpires AS _sessionExpires, s.id AS _sessionID, u.*
+ FROM %T u JOIN %T s ON u.phid = s.userPHID
AND s.type LIKE %> AND s.sessionKey = %s',
$user_table->getTableName(),
$session_table->getTableName(),
@@ -20,6 +24,29 @@
return null;
}
+ $expires = $info['_sessionExpires'];
+ $id = $info['_sessionID'];
+ unset($info['_sessionExpires']);
+ unset($info['_sessionID']);
+
+ $ttl = PhabricatorAuthSession::getSessionTypeTTL($session_type);
+
+ // If more than 20% of the time on this session has been used, refresh the
+ // TTL back up to the full duration. The idea here is that sessions are
+ // good forever if used regularly, but get GC'd when they fall out of use.
+
+ if (time() + (0.80 * $ttl) > $expires) {
+ $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
+ $conn_w = $session_table->establishConnection('w');
+ queryfx(
+ $conn_w,
+ 'UPDATE %T SET sessionExpires = UNIX_TIMESTAMP() + %d WHERE id = %d',
+ $session_table->getTableName(),
+ $ttl,
+ $id);
+ unset($unguarded);
+ }
+
return $user_table->loadFromArray($info);
}
@@ -84,6 +111,7 @@
// Consume entropy to generate a new session key, forestalling the eventual
// heat death of the universe.
$session_key = Filesystem::readRandomCharacters(40);
+ $session_ttl = PhabricatorAuthSession::getSessionTypeTTL($session_type);
// Load all the currently active sessions.
$sessions = queryfx_all(
@@ -119,12 +147,14 @@
// care if we race here or not.
queryfx(
$conn_w,
- 'INSERT IGNORE INTO %T (userPHID, type, sessionKey, sessionStart)
- VALUES (%s, %s, %s, 0)',
+ 'INSERT IGNORE INTO %T
+ (userPHID, type, sessionKey, sessionStart, sessionExpires)
+ VALUES (%s, %s, %s, 0, UNIX_TIMESTAMP() + %d)',
$session_table->getTableName(),
$identity_phid,
$establish_type,
- PhabricatorHash::digest($session_key));
+ PhabricatorHash::digest($session_key),
+ $session_ttl);
break;
}
}
@@ -144,10 +174,12 @@
queryfx(
$conn_w,
- 'UPDATE %T SET sessionKey = %s, sessionStart = UNIX_TIMESTAMP()
+ 'UPDATE %T SET sessionKey = %s, sessionStart = UNIX_TIMESTAMP(),
+ sessionExpires = UNIX_TIMESTAMP() + %d
WHERE userPHID = %s AND type = %s AND sessionKey = %s',
$session_table->getTableName(),
PhabricatorHash::digest($session_key),
+ $session_ttl,
$identity_phid,
$establish_type,
$expect_key);
Index: src/applications/auth/garbagecollector/PhabricatorAuthSessionGarbageCollector.php
===================================================================
--- /dev/null
+++ src/applications/auth/garbagecollector/PhabricatorAuthSessionGarbageCollector.php
@@ -0,0 +1,18 @@
+<?php
+
+final class PhabricatorAuthSessionGarbageCollector
+ extends PhabricatorGarbageCollector {
+
+ public function collectGarbage() {
+ $session_table = new PhabricatorAuthSession();
+ $conn_w = $session_table->establishConnection('w');
+
+ queryfx(
+ $conn_w,
+ 'DELETE FROM %T WHERE sessionExpires <= UNIX_TIMESTAMP() LIMIT 100',
+ $session_table->getTableName());
+
+ return ($conn_w->getAffectedRows() == 100);
+ }
+
+}
Index: src/applications/auth/storage/PhabricatorAuthSession.php
===================================================================
--- src/applications/auth/storage/PhabricatorAuthSession.php
+++ src/applications/auth/storage/PhabricatorAuthSession.php
@@ -10,6 +10,7 @@
protected $type;
protected $sessionKey;
protected $sessionStart;
+ protected $sessionExpires;
private $identityObject = self::ATTACHABLE;
@@ -38,6 +39,18 @@
return $this->assertAttached($this->identityObject);
}
+ public static function getSessionTypeTTL($session_type) {
+ switch ($session_type) {
+ case self::TYPE_WEB:
+ return (60 * 60 * 24 * 30); // 30 days
+ case self::TYPE_CONDUIT:
+ return (60 * 60 * 24); // 24 hours
+ default:
+ throw new Exception(pht('Unknown session type "%s".', $session_type));
+ }
+ }
+
+
/* -( PhabricatorPolicyInterface )----------------------------------------- */
Index: src/applications/settings/panel/PhabricatorSettingsPanelSessions.php
===================================================================
--- src/applications/settings/panel/PhabricatorSettingsPanelSessions.php
+++ src/applications/settings/panel/PhabricatorSettingsPanelSessions.php
@@ -60,6 +60,7 @@
substr($session->getSessionKey(), 0, 12),
$session->getType(),
phabricator_datetime($session->getSessionStart(), $viewer),
+ phabricator_datetime($session->getSessionExpires(), $viewer),
);
}
@@ -72,6 +73,7 @@
pht('Session'),
pht('Type'),
pht('Created'),
+ pht('Expires'),
));
$table->setColumnClasses(
array(
@@ -79,6 +81,7 @@
'n',
'',
'right',
+ 'right',
));

File Metadata

Mime Type
text/plain
Expires
Wed, May 15, 12:44 PM (2 w, 4 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6290478
Default Alt Text
D7976.id18048.diff (7 KB)

Event Timeline