Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14411137
D10133.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
9 KB
Referenced Files
None
Subscribers
None
D10133.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1192,6 +1192,7 @@
'PhabricatorAuthProviderConfigTransaction' => 'applications/auth/storage/PhabricatorAuthProviderConfigTransaction.php',
'PhabricatorAuthProviderConfigTransactionQuery' => 'applications/auth/query/PhabricatorAuthProviderConfigTransactionQuery.php',
'PhabricatorAuthRegisterController' => 'applications/auth/controller/PhabricatorAuthRegisterController.php',
+ 'PhabricatorAuthRevokeTokenController' => 'applications/auth/controller/PhabricatorAuthRevokeTokenController.php',
'PhabricatorAuthSession' => 'applications/auth/storage/PhabricatorAuthSession.php',
'PhabricatorAuthSessionEngine' => 'applications/auth/engine/PhabricatorAuthSessionEngine.php',
'PhabricatorAuthSessionGarbageCollector' => 'applications/auth/garbagecollector/PhabricatorAuthSessionGarbageCollector.php',
@@ -2146,6 +2147,7 @@
'PhabricatorSettingsPanelSSHKeys' => 'applications/settings/panel/PhabricatorSettingsPanelSSHKeys.php',
'PhabricatorSettingsPanelSearchPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelSearchPreferences.php',
'PhabricatorSettingsPanelSessions' => 'applications/settings/panel/PhabricatorSettingsPanelSessions.php',
+ 'PhabricatorSettingsPanelTokens' => 'applications/settings/panel/PhabricatorSettingsPanelTokens.php',
'PhabricatorSetupCheck' => 'applications/config/check/PhabricatorSetupCheck.php',
'PhabricatorSetupCheckAPC' => 'applications/config/check/PhabricatorSetupCheckAPC.php',
'PhabricatorSetupCheckAphlict' => 'applications/notification/setup/PhabricatorSetupCheckAphlict.php',
@@ -3986,6 +3988,7 @@
'PhabricatorAuthProviderConfigTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorAuthProviderConfigTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorAuthRegisterController' => 'PhabricatorAuthController',
+ 'PhabricatorAuthRevokeTokenController' => 'PhabricatorAuthController',
'PhabricatorAuthSession' => array(
'PhabricatorAuthDAO',
'PhabricatorPolicyInterface',
@@ -4999,6 +5002,7 @@
'PhabricatorSettingsPanelSSHKeys' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelSearchPreferences' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelSessions' => 'PhabricatorSettingsPanel',
+ 'PhabricatorSettingsPanelTokens' => 'PhabricatorSettingsPanel',
'PhabricatorSetupCheckAPC' => 'PhabricatorSetupCheck',
'PhabricatorSetupCheckAphlict' => 'PhabricatorSetupCheck',
'PhabricatorSetupCheckAuth' => 'PhabricatorSetupCheck',
diff --git a/src/applications/auth/application/PhabricatorAuthApplication.php b/src/applications/auth/application/PhabricatorAuthApplication.php
--- a/src/applications/auth/application/PhabricatorAuthApplication.php
+++ b/src/applications/auth/application/PhabricatorAuthApplication.php
@@ -103,6 +103,8 @@
=> 'PhabricatorAuthConfirmLinkController',
'session/terminate/(?P<id>[^/]+)/'
=> 'PhabricatorAuthTerminateSessionController',
+ 'token/revoke/(?P<id>[^/]+)/'
+ => 'PhabricatorAuthRevokeTokenController',
'session/downgrade/'
=> 'PhabricatorAuthDowngradeSessionController',
'multifactor/'
diff --git a/src/applications/auth/controller/PhabricatorAuthRevokeTokenController.php b/src/applications/auth/controller/PhabricatorAuthRevokeTokenController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/auth/controller/PhabricatorAuthRevokeTokenController.php
@@ -0,0 +1,78 @@
+<?php
+
+final class PhabricatorAuthRevokeTokenController
+ extends PhabricatorAuthController {
+
+ private $id;
+
+ public function willProcessRequest(array $data) {
+ $this->id = $data['id'];
+ }
+
+ public function processRequest() {
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ $is_all = ($this->id === 'all');
+
+ $query = id(new PhabricatorAuthTemporaryTokenQuery())
+ ->setViewer($viewer)
+ ->withObjectPHIDs(array($viewer->getPHID()));
+ if (!$is_all) {
+ $query->withIDs(array($this->id));
+ }
+
+ $tokens = $query->execute();
+ foreach ($tokens as $key => $token) {
+ if (!$token->isRevocable()) {
+ // Don't revoke unrevocable tokens.
+ unset($tokens[$key]);
+ }
+ }
+
+ $panel_uri = '/settings/panel/tokens/';
+
+ if (!$tokens) {
+ return $this->newDialog()
+ ->setTitle(pht('No Matching Tokens'))
+ ->appendParagraph(
+ pht('There are no matching tokens to revoke.'))
+ ->appendParagraph(
+ pht(
+ '(Some types of token can not be revoked, and you can not revoke '.
+ 'tokens which have already expired.)'))
+ ->addCancelButton($panel_uri);
+ }
+
+ if ($request->isDialogFormPost()) {
+ foreach ($tokens as $token) {
+ $token->setTokenExpires(PhabricatorTime::getNow() - 1)->save();
+ }
+ return id(new AphrontRedirectResponse())->setURI($panel_uri);
+ }
+
+ if ($is_all) {
+ $title = pht('Revoke Tokens?');
+ $short = pht('Revoke Tokens');
+ $body = pht(
+ 'Really revoke all tokens? Among other temporary authorizations, '.
+ 'this will disable any outstanding password reset or account '.
+ 'recovery links.');
+ } else {
+ $title = pht('Revoke Token?');
+ $short = pht('Revoke Token');
+ $body = pht(
+ 'Really revoke this token? Any temporary authorization it enables '.
+ 'will be disabled.');
+ }
+
+ return $this->newDialog()
+ ->setTitle($title)
+ ->setShortTitle($short)
+ ->appendParagraph($body)
+ ->addSubmitButton(pht('Revoke'))
+ ->addCancelButton($panel_uri);
+ }
+
+
+}
diff --git a/src/applications/auth/storage/PhabricatorAuthTemporaryToken.php b/src/applications/auth/storage/PhabricatorAuthTemporaryToken.php
--- a/src/applications/auth/storage/PhabricatorAuthTemporaryToken.php
+++ b/src/applications/auth/storage/PhabricatorAuthTemporaryToken.php
@@ -17,6 +17,33 @@
) + parent::getConfiguration();
}
+ public function getTokenReadableTypeName() {
+ // Eventually, it would be nice to let applications implement token types
+ // so we can put this in modular subclasses.
+ switch ($this->tokenType) {
+ case PhabricatorAuthSessionEngine::ONETIME_TEMPORARY_TOKEN_TYPE:
+ return pht('One-Time Login Token');
+ case PhabricatorAuthSessionEngine::PASSWORD_TEMPORARY_TOKEN_TYPE:
+ return pht('Password Reset Token');
+ }
+
+ return $this->tokenType;
+ }
+
+ public function isRevocable() {
+ if ($this->tokenExpires < time()) {
+ return false;
+ }
+
+ switch ($this->tokenType) {
+ case PhabricatorAuthSessionEngine::ONETIME_TEMPORARY_TOKEN_TYPE:
+ case PhabricatorAuthSessionEngine::PASSWORD_TEMPORARY_TOKEN_TYPE:
+ return true;
+ }
+
+ return false;
+ }
+
/* -( PhabricatorPolicyInterface )----------------------------------------- */
@@ -40,5 +67,4 @@
return null;
}
-
}
diff --git a/src/applications/settings/panel/PhabricatorSettingsPanelTokens.php b/src/applications/settings/panel/PhabricatorSettingsPanelTokens.php
new file mode 100644
--- /dev/null
+++ b/src/applications/settings/panel/PhabricatorSettingsPanelTokens.php
@@ -0,0 +1,100 @@
+<?php
+
+final class PhabricatorSettingsPanelTokens
+ extends PhabricatorSettingsPanel {
+
+ public function getPanelKey() {
+ return 'tokens';
+ }
+
+ public function getPanelName() {
+ return pht('Temporary Tokens');
+ }
+
+ public function getPanelGroup() {
+ return pht('Sessions and Logs');
+ }
+
+ public function isEnabled() {
+ return true;
+ }
+
+ public function processRequest(AphrontRequest $request) {
+ $viewer = $request->getUser();
+
+ $tokens = id(new PhabricatorAuthTemporaryTokenQuery())
+ ->setViewer($viewer)
+ ->withObjectPHIDs(array($viewer->getPHID()))
+ ->execute();
+
+ $rows = array();
+ foreach ($tokens as $token) {
+
+ if ($token->isRevocable()) {
+ $button = javelin_tag(
+ 'a',
+ array(
+ 'href' => '/auth/token/revoke/'.$token->getID().'/',
+ 'class' => 'small grey button',
+ 'sigil' => 'workflow',
+ ),
+ pht('Revoke'));
+ } else {
+ $button = javelin_tag(
+ 'a',
+ array(
+ 'class' => 'small grey button disabled',
+ ),
+ pht('Revoke'));
+ }
+
+ if ($token->getTokenExpires() >= time()) {
+ $expiry = phabricator_datetime($token->getTokenExpires(), $viewer);
+ } else {
+ $expiry = pht('Expired');
+ }
+
+ $rows[] = array(
+ $token->getTokenReadableTypeName(),
+ $expiry,
+ $button,
+ );
+ }
+
+ $table = new AphrontTableView($rows);
+ $table->setNoDataString(pht("You don't have any active tokens."));
+ $table->setHeaders(
+ array(
+ pht('Type'),
+ pht('Expires'),
+ pht(''),
+ ));
+ $table->setColumnClasses(
+ array(
+ 'wide',
+ 'right',
+ 'action',
+ ));
+
+
+ $terminate_icon = id(new PHUIIconView())
+ ->setIconFont('fa-exclamation-triangle');
+ $terminate_button = id(new PHUIButtonView())
+ ->setText(pht('Revoke All'))
+ ->setHref('/auth/token/revoke/all/')
+ ->setTag('a')
+ ->setWorkflow(true)
+ ->setIcon($terminate_icon);
+
+ $header = id(new PHUIHeaderView())
+ ->setHeader(pht('Temporary Tokens'))
+ ->addActionLink($terminate_button);
+
+ $panel = id(new PHUIObjectBoxView())
+ ->setHeader($header)
+ ->appendChild($table);
+
+ return $panel;
+ }
+
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Dec 25, 8:59 AM (10 h, 16 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6925720
Default Alt Text
D10133.diff (9 KB)
Attached To
Mode
D10133: Add an explicit temporary token management page to Settings
Attached
Detach File
Event Timeline
Log In to Comment