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',
|
'PhabricatorAuthProviderPassword' => 'applications/auth/provider/PhabricatorAuthProviderPassword.php',
|
||||||
'PhabricatorAuthProviderPersona' => 'applications/auth/provider/PhabricatorAuthProviderPersona.php',
|
'PhabricatorAuthProviderPersona' => 'applications/auth/provider/PhabricatorAuthProviderPersona.php',
|
||||||
'PhabricatorAuthRegisterController' => 'applications/auth/controller/PhabricatorAuthRegisterController.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',
|
'PhabricatorAuthStartController' => 'applications/auth/controller/PhabricatorAuthStartController.php',
|
||||||
'PhabricatorAuthUnlinkController' => 'applications/auth/controller/PhabricatorAuthUnlinkController.php',
|
'PhabricatorAuthUnlinkController' => 'applications/auth/controller/PhabricatorAuthUnlinkController.php',
|
||||||
'PhabricatorAuthValidateController' => 'applications/auth/controller/PhabricatorAuthValidateController.php',
|
'PhabricatorAuthValidateController' => 'applications/auth/controller/PhabricatorAuthValidateController.php',
|
||||||
|
@ -1915,6 +1917,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSettingsPanelPassword' => 'applications/settings/panel/PhabricatorSettingsPanelPassword.php',
|
'PhabricatorSettingsPanelPassword' => 'applications/settings/panel/PhabricatorSettingsPanelPassword.php',
|
||||||
'PhabricatorSettingsPanelSSHKeys' => 'applications/settings/panel/PhabricatorSettingsPanelSSHKeys.php',
|
'PhabricatorSettingsPanelSSHKeys' => 'applications/settings/panel/PhabricatorSettingsPanelSSHKeys.php',
|
||||||
'PhabricatorSettingsPanelSearchPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelSearchPreferences.php',
|
'PhabricatorSettingsPanelSearchPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelSearchPreferences.php',
|
||||||
|
'PhabricatorSettingsPanelSessions' => 'applications/settings/panel/PhabricatorSettingsPanelSessions.php',
|
||||||
'PhabricatorSetupCheck' => 'applications/config/check/PhabricatorSetupCheck.php',
|
'PhabricatorSetupCheck' => 'applications/config/check/PhabricatorSetupCheck.php',
|
||||||
'PhabricatorSetupCheckAPC' => 'applications/config/check/PhabricatorSetupCheckAPC.php',
|
'PhabricatorSetupCheckAPC' => 'applications/config/check/PhabricatorSetupCheckAPC.php',
|
||||||
'PhabricatorSetupCheckAuth' => 'applications/config/check/PhabricatorSetupCheckAuth.php',
|
'PhabricatorSetupCheckAuth' => 'applications/config/check/PhabricatorSetupCheckAuth.php',
|
||||||
|
@ -3760,6 +3763,12 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorAuthProviderPassword' => 'PhabricatorAuthProvider',
|
'PhabricatorAuthProviderPassword' => 'PhabricatorAuthProvider',
|
||||||
'PhabricatorAuthProviderPersona' => 'PhabricatorAuthProvider',
|
'PhabricatorAuthProviderPersona' => 'PhabricatorAuthProvider',
|
||||||
'PhabricatorAuthRegisterController' => 'PhabricatorAuthController',
|
'PhabricatorAuthRegisterController' => 'PhabricatorAuthController',
|
||||||
|
'PhabricatorAuthSession' =>
|
||||||
|
array(
|
||||||
|
0 => 'PhabricatorAuthDAO',
|
||||||
|
1 => 'PhabricatorPolicyInterface',
|
||||||
|
),
|
||||||
|
'PhabricatorAuthSessionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
'PhabricatorAuthStartController' => 'PhabricatorAuthController',
|
'PhabricatorAuthStartController' => 'PhabricatorAuthController',
|
||||||
'PhabricatorAuthUnlinkController' => 'PhabricatorAuthController',
|
'PhabricatorAuthUnlinkController' => 'PhabricatorAuthController',
|
||||||
'PhabricatorAuthValidateController' => 'PhabricatorAuthController',
|
'PhabricatorAuthValidateController' => 'PhabricatorAuthController',
|
||||||
|
@ -4548,6 +4557,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSettingsPanelPassword' => 'PhabricatorSettingsPanel',
|
'PhabricatorSettingsPanelPassword' => 'PhabricatorSettingsPanel',
|
||||||
'PhabricatorSettingsPanelSSHKeys' => 'PhabricatorSettingsPanel',
|
'PhabricatorSettingsPanelSSHKeys' => 'PhabricatorSettingsPanel',
|
||||||
'PhabricatorSettingsPanelSearchPreferences' => 'PhabricatorSettingsPanel',
|
'PhabricatorSettingsPanelSearchPreferences' => 'PhabricatorSettingsPanel',
|
||||||
|
'PhabricatorSettingsPanelSessions' => 'PhabricatorSettingsPanel',
|
||||||
'PhabricatorSetupCheckAPC' => 'PhabricatorSetupCheck',
|
'PhabricatorSetupCheckAPC' => 'PhabricatorSetupCheck',
|
||||||
'PhabricatorSetupCheckAuth' => 'PhabricatorSetupCheck',
|
'PhabricatorSetupCheckAuth' => 'PhabricatorSetupCheck',
|
||||||
'PhabricatorSetupCheckBaseURI' => '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
|
'SELECT u.* FROM %T u JOIN %T s ON u.phid = s.userPHID
|
||||||
AND s.type LIKE %> AND s.sessionKey = %s',
|
AND s.type LIKE %> AND s.sessionKey = %s',
|
||||||
$user->getTableName(),
|
$user->getTableName(),
|
||||||
'phabricator_session',
|
PhabricatorUser::SESSION_TABLE,
|
||||||
'web-',
|
'web-',
|
||||||
PhabricatorHash::digest($phsid));
|
PhabricatorHash::digest($phsid));
|
||||||
if ($info) {
|
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