mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-20 20:40:56 +01:00
Add an "active login sessions" table to Settings
Summary: Ref T4310. Ref T3720. Partly, this makes it easier for users to understand login sessions. Partly, it makes it easier for me to make changes to login sessions for T4310 / T3720 without messing anything up. Test Plan: {F101512} Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T3720, T4310 Differential Revision: https://secure.phabricator.com/D7954
This commit is contained in:
parent
220d680f37
commit
3d9e328fb3
5 changed files with 251 additions and 1 deletions
|
@ -1202,6 +1202,8 @@ phutil_register_library_map(array(
|
|||
'PhabricatorAuthProviderPassword' => 'applications/auth/provider/PhabricatorAuthProviderPassword.php',
|
||||
'PhabricatorAuthProviderPersona' => 'applications/auth/provider/PhabricatorAuthProviderPersona.php',
|
||||
'PhabricatorAuthRegisterController' => 'applications/auth/controller/PhabricatorAuthRegisterController.php',
|
||||
'PhabricatorAuthSession' => 'applications/auth/storage/PhabricatorAuthSession.php',
|
||||
'PhabricatorAuthSessionQuery' => 'applications/auth/query/PhabricatorAuthSessionQuery.php',
|
||||
'PhabricatorAuthStartController' => 'applications/auth/controller/PhabricatorAuthStartController.php',
|
||||
'PhabricatorAuthUnlinkController' => 'applications/auth/controller/PhabricatorAuthUnlinkController.php',
|
||||
'PhabricatorAuthValidateController' => 'applications/auth/controller/PhabricatorAuthValidateController.php',
|
||||
|
@ -1915,6 +1917,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorSettingsPanelPassword' => 'applications/settings/panel/PhabricatorSettingsPanelPassword.php',
|
||||
'PhabricatorSettingsPanelSSHKeys' => 'applications/settings/panel/PhabricatorSettingsPanelSSHKeys.php',
|
||||
'PhabricatorSettingsPanelSearchPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelSearchPreferences.php',
|
||||
'PhabricatorSettingsPanelSessions' => 'applications/settings/panel/PhabricatorSettingsPanelSessions.php',
|
||||
'PhabricatorSetupCheck' => 'applications/config/check/PhabricatorSetupCheck.php',
|
||||
'PhabricatorSetupCheckAPC' => 'applications/config/check/PhabricatorSetupCheckAPC.php',
|
||||
'PhabricatorSetupCheckAuth' => 'applications/config/check/PhabricatorSetupCheckAuth.php',
|
||||
|
@ -3760,6 +3763,12 @@ phutil_register_library_map(array(
|
|||
'PhabricatorAuthProviderPassword' => 'PhabricatorAuthProvider',
|
||||
'PhabricatorAuthProviderPersona' => 'PhabricatorAuthProvider',
|
||||
'PhabricatorAuthRegisterController' => 'PhabricatorAuthController',
|
||||
'PhabricatorAuthSession' =>
|
||||
array(
|
||||
0 => 'PhabricatorAuthDAO',
|
||||
1 => 'PhabricatorPolicyInterface',
|
||||
),
|
||||
'PhabricatorAuthSessionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorAuthStartController' => 'PhabricatorAuthController',
|
||||
'PhabricatorAuthUnlinkController' => 'PhabricatorAuthController',
|
||||
'PhabricatorAuthValidateController' => 'PhabricatorAuthController',
|
||||
|
@ -4548,6 +4557,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorSettingsPanelPassword' => 'PhabricatorSettingsPanel',
|
||||
'PhabricatorSettingsPanelSSHKeys' => 'PhabricatorSettingsPanel',
|
||||
'PhabricatorSettingsPanelSearchPreferences' => 'PhabricatorSettingsPanel',
|
||||
'PhabricatorSettingsPanelSessions' => 'PhabricatorSettingsPanel',
|
||||
'PhabricatorSetupCheckAPC' => 'PhabricatorSetupCheck',
|
||||
'PhabricatorSetupCheckAuth' => 'PhabricatorSetupCheck',
|
||||
'PhabricatorSetupCheckBaseURI' => 'PhabricatorSetupCheck',
|
||||
|
|
73
src/applications/auth/query/PhabricatorAuthSessionQuery.php
Normal file
73
src/applications/auth/query/PhabricatorAuthSessionQuery.php
Normal file
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorAuthSessionQuery
|
||||
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||
|
||||
private $identityPHIDs;
|
||||
|
||||
public function withIdentityPHIDs(array $identity_phids) {
|
||||
$this->identityPHIDs = $identity_phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function loadPage() {
|
||||
$table = new PhabricatorAuthSession();
|
||||
$conn_r = $table->establishConnection('r');
|
||||
|
||||
$data = queryfx_all(
|
||||
$conn_r,
|
||||
'SELECT * FROM %T %Q %Q %Q',
|
||||
$table->getTableName(),
|
||||
$this->buildWhereClause($conn_r),
|
||||
$this->buildOrderClause($conn_r),
|
||||
$this->buildLimitClause($conn_r));
|
||||
|
||||
return $table->loadAllFromArray($data);
|
||||
}
|
||||
|
||||
protected function willFilterPage(array $sessions) {
|
||||
$identity_phids = mpull($sessions, 'getUserPHID');
|
||||
|
||||
$identity_objects = id(new PhabricatorObjectQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->setParentQuery($this)
|
||||
->withPHIDs($identity_phids)
|
||||
->execute();
|
||||
$identity_objects = mpull($identity_objects, null, 'getPHID');
|
||||
|
||||
foreach ($sessions as $key => $session) {
|
||||
$identity_object = idx($identity_objects, $session->getUserPHID());
|
||||
if (!$identity_object) {
|
||||
unset($sessions[$key]);
|
||||
} else {
|
||||
$session->attachIdentityObject($identity_object);
|
||||
}
|
||||
}
|
||||
|
||||
return $sessions;
|
||||
}
|
||||
|
||||
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
||||
$where = array();
|
||||
|
||||
if ($this->identityPHIDs) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'userPHID IN (%Ls)',
|
||||
$this->identityPHIDs);
|
||||
}
|
||||
|
||||
$where[] = $this->buildPagingClause($conn_r);
|
||||
|
||||
return $this->formatWhereClause($where);
|
||||
}
|
||||
|
||||
public function getPagingColumn() {
|
||||
return 'sessionKey';
|
||||
}
|
||||
|
||||
public function getQueryApplicationClass() {
|
||||
return 'PhabricatorApplicationAuth';
|
||||
}
|
||||
|
||||
}
|
72
src/applications/auth/storage/PhabricatorAuthSession.php
Normal file
72
src/applications/auth/storage/PhabricatorAuthSession.php
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorAuthSession extends PhabricatorAuthDAO
|
||||
implements PhabricatorPolicyInterface {
|
||||
|
||||
protected $userPHID;
|
||||
protected $type;
|
||||
protected $sessionKey;
|
||||
protected $sessionStart;
|
||||
|
||||
private $identityObject = self::ATTACHABLE;
|
||||
|
||||
public function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_IDS => self::IDS_MANUAL,
|
||||
self::CONFIG_TIMESTAMPS => false,
|
||||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
public function getApplicationName() {
|
||||
// This table predates the "Auth" application, and really all applications.
|
||||
return 'user';
|
||||
}
|
||||
|
||||
public function getTableName() {
|
||||
// This is a very old table with a nonstandard name.
|
||||
return PhabricatorUser::SESSION_TABLE;
|
||||
}
|
||||
|
||||
public function attachIdentityObject($identity_object) {
|
||||
$this->identityObject = $identity_object;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIdentityObject() {
|
||||
return $this->assertAttached($this->identityObject);
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
||||
public function getCapabilities() {
|
||||
return array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
);
|
||||
}
|
||||
|
||||
public function getPolicy($capability) {
|
||||
return PhabricatorPolicies::POLICY_NOONE;
|
||||
}
|
||||
|
||||
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
||||
if (!$viewer->getPHID()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$object = $this->getIdentityObject();
|
||||
if ($object instanceof PhabricatorUser) {
|
||||
return ($object->getPHID() == $viewer->getPHID());
|
||||
} else if ($object instanceof PhabricatorExternalAccount) {
|
||||
return ($object->getUserPHID() == $viewer->getPHID());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return pht('A session is visible only to its owner.');
|
||||
}
|
||||
|
||||
}
|
|
@ -44,7 +44,7 @@ abstract class PhabricatorController extends AphrontController {
|
|||
'SELECT u.* FROM %T u JOIN %T s ON u.phid = s.userPHID
|
||||
AND s.type LIKE %> AND s.sessionKey = %s',
|
||||
$user->getTableName(),
|
||||
'phabricator_session',
|
||||
PhabricatorUser::SESSION_TABLE,
|
||||
'web-',
|
||||
PhabricatorHash::digest($phsid));
|
||||
if ($info) {
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorSettingsPanelSessions
|
||||
extends PhabricatorSettingsPanel {
|
||||
|
||||
public function getPanelKey() {
|
||||
return 'sessions';
|
||||
}
|
||||
|
||||
public function getPanelName() {
|
||||
return pht('Sessions');
|
||||
}
|
||||
|
||||
public function getPanelGroup() {
|
||||
return pht('Authentication');
|
||||
}
|
||||
|
||||
public function isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function processRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getUser();
|
||||
|
||||
$accounts = id(new PhabricatorExternalAccountQuery())
|
||||
->setViewer($viewer)
|
||||
->withUserPHIDs(array($viewer->getPHID()))
|
||||
->execute();
|
||||
|
||||
$identity_phids = mpull($accounts, 'getPHID');
|
||||
$identity_phids[] = $viewer->getPHID();
|
||||
|
||||
$sessions = id(new PhabricatorAuthSessionQuery())
|
||||
->setViewer($viewer)
|
||||
->withIdentityPHIDs($identity_phids)
|
||||
->execute();
|
||||
|
||||
$handles = id(new PhabricatorHandleQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs($identity_phids)
|
||||
->execute();
|
||||
|
||||
// TODO: Once this has a real ID column, use that instead.
|
||||
$sessions = msort($sessions, 'getSessionStart');
|
||||
$sessions = array_reverse($sessions);
|
||||
|
||||
$current_key = PhabricatorHash::digest($request->getCookie('phsid'));
|
||||
|
||||
$rows = array();
|
||||
$rowc = array();
|
||||
foreach ($sessions as $session) {
|
||||
if ($session->getSessionKey() == $current_key) {
|
||||
$rowc[] = 'highlighted';
|
||||
} else {
|
||||
$rowc[] = null;
|
||||
}
|
||||
|
||||
$rows[] = array(
|
||||
$handles[$session->getUserPHID()]->renderLink(),
|
||||
substr($session->getSessionKey(), 0, 12),
|
||||
$session->getType(),
|
||||
phabricator_datetime($session->getSessionStart(), $viewer),
|
||||
);
|
||||
}
|
||||
|
||||
$table = new AphrontTableView($rows);
|
||||
$table->setNoDataString(pht("You don't have any active sessions."));
|
||||
$table->setRowClasses($rowc);
|
||||
$table->setHeaders(
|
||||
array(
|
||||
pht('Identity'),
|
||||
pht('Session'),
|
||||
pht('Type'),
|
||||
pht('Created'),
|
||||
));
|
||||
$table->setColumnClasses(
|
||||
array(
|
||||
'wide',
|
||||
'n',
|
||||
'',
|
||||
'right',
|
||||
));
|
||||
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader(pht('Active Login Sessions'));
|
||||
|
||||
$panel = id(new PHUIObjectBoxView())
|
||||
->setHeader($header)
|
||||
->appendChild($table);
|
||||
|
||||
return $panel;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue