Page MenuHomePhabricator

D10989.diff
No OneTemporary

D10989.diff

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
@@ -199,6 +199,7 @@
'ConduitConnectConduitAPIMethod' => 'applications/conduit/method/ConduitConnectConduitAPIMethod.php',
'ConduitConnectionGarbageCollector' => 'applications/conduit/garbagecollector/ConduitConnectionGarbageCollector.php',
'ConduitException' => 'applications/conduit/protocol/exception/ConduitException.php',
+ 'ConduitGetCapabilitiesConduitAPIMethod' => 'applications/conduit/method/ConduitGetCapabilitiesConduitAPIMethod.php',
'ConduitGetCertificateConduitAPIMethod' => 'applications/conduit/method/ConduitGetCertificateConduitAPIMethod.php',
'ConduitLogGarbageCollector' => 'applications/conduit/garbagecollector/ConduitLogGarbageCollector.php',
'ConduitMethodDoesNotExistException' => 'applications/conduit/protocol/exception/ConduitMethodDoesNotExistException.php',
@@ -1434,6 +1435,7 @@
'PhabricatorConduitToken' => 'applications/conduit/storage/PhabricatorConduitToken.php',
'PhabricatorConduitTokenController' => 'applications/conduit/controller/PhabricatorConduitTokenController.php',
'PhabricatorConduitTokenEditController' => 'applications/conduit/controller/PhabricatorConduitTokenEditController.php',
+ 'PhabricatorConduitTokenHandshakeController' => 'applications/conduit/controller/PhabricatorConduitTokenHandshakeController.php',
'PhabricatorConduitTokenQuery' => 'applications/conduit/query/PhabricatorConduitTokenQuery.php',
'PhabricatorConduitTokenTerminateController' => 'applications/conduit/controller/PhabricatorConduitTokenTerminateController.php',
'PhabricatorConfigAllController' => 'applications/config/controller/PhabricatorConfigAllController.php',
@@ -3212,6 +3214,7 @@
'ConduitConnectConduitAPIMethod' => 'ConduitAPIMethod',
'ConduitConnectionGarbageCollector' => 'PhabricatorGarbageCollector',
'ConduitException' => 'Exception',
+ 'ConduitGetCapabilitiesConduitAPIMethod' => 'ConduitAPIMethod',
'ConduitGetCertificateConduitAPIMethod' => 'ConduitAPIMethod',
'ConduitLogGarbageCollector' => 'PhabricatorGarbageCollector',
'ConduitMethodDoesNotExistException' => 'ConduitMethodNotFoundException',
@@ -4557,6 +4560,7 @@
),
'PhabricatorConduitTokenController' => 'PhabricatorConduitController',
'PhabricatorConduitTokenEditController' => 'PhabricatorConduitController',
+ 'PhabricatorConduitTokenHandshakeController' => 'PhabricatorConduitController',
'PhabricatorConduitTokenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorConduitTokenTerminateController' => 'PhabricatorConduitController',
'PhabricatorConfigAllController' => 'PhabricatorConfigController',
diff --git a/src/applications/conduit/application/PhabricatorConduitApplication.php b/src/applications/conduit/application/PhabricatorConduitApplication.php
--- a/src/applications/conduit/application/PhabricatorConduitApplication.php
+++ b/src/applications/conduit/application/PhabricatorConduitApplication.php
@@ -50,6 +50,7 @@
'PhabricatorConduitTokenEditController',
'token/terminate/(?:(?P<id>\d+)/)?' =>
'PhabricatorConduitTokenTerminateController',
+ 'login/' => 'PhabricatorConduitTokenHandshakeController',
),
'/api/(?P<method>[^/]+)' => 'PhabricatorConduitAPIController',
);
diff --git a/src/applications/conduit/controller/PhabricatorConduitAPIController.php b/src/applications/conduit/controller/PhabricatorConduitAPIController.php
--- a/src/applications/conduit/controller/PhabricatorConduitAPIController.php
+++ b/src/applications/conduit/controller/PhabricatorConduitAPIController.php
@@ -301,22 +301,22 @@
'ERR-INVALID-AUTH',
pht(
'API token "%s" has the wrong length. API tokens should be '.
- '32 characters long.'),
+ '32 characters long.',
+ $token_string),
);
}
$type = head(explode('-', $token_string));
- switch ($type) {
- case 'api':
- case 'tmp':
- break;
- default:
- return array(
- 'ERR-INVALID-AUTH',
- pht(
- 'API token "%s" has the wrong format. API tokens should begin '.
- 'with "api-" or "tmp-" and be 32 characters long.',
- $token_string),
+ $valid_types = PhabricatorConduitToken::getAllTokenTypes();
+ $valid_types = array_fuse($valid_types);
+ if (empty($valid_types[$type])) {
+ return array(
+ 'ERR-INVALID-AUTH',
+ pht(
+ 'API token "%s" has the wrong format. API tokens should be '.
+ '32 characters long and begin with one of these prefixes: %s.',
+ $token_string,
+ implode(', ', $valid_types)),
);
}
@@ -348,6 +348,19 @@
}
}
+ // If this is a "cli-" token, it expires shortly after it is generated
+ // by default. Once it is actually used, we extend its lifetime and make
+ // it permanent. This allows stray tokens to get cleaned up automatically
+ // if they aren't being used.
+ if ($token->getTokenType() == PhabricatorConduitToken::TYPE_COMMANDLINE) {
+ if ($token->getExpires()) {
+ $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
+ $token->setExpires(null);
+ $token->save();
+ unset($unguarded);
+ }
+ }
+
$user = $token->getObject();
if (!($user instanceof PhabricatorUser)) {
return array(
diff --git a/src/applications/conduit/controller/PhabricatorConduitTokenHandshakeController.php b/src/applications/conduit/controller/PhabricatorConduitTokenHandshakeController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/conduit/controller/PhabricatorConduitTokenHandshakeController.php
@@ -0,0 +1,46 @@
+<?php
+
+final class PhabricatorConduitTokenHandshakeController
+ extends PhabricatorConduitController {
+
+ public function handleRequest(AphrontRequest $request) {
+ $viewer = $request->getViewer();
+
+ id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
+ $viewer,
+ $request,
+ '/');
+
+ $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
+ $token = PhabricatorConduitToken::initializeNewToken(
+ $viewer->getPHID(),
+ PhabricatorConduitToken::TYPE_COMMANDLINE);
+ $token->save();
+ unset($unguarded);
+
+ $form = id(new AphrontFormView())
+ ->setUser($viewer)
+ ->appendRemarkupInstructions(
+ pht(
+ 'Copy-paste the API Token below to grant access to your account.'))
+ ->appendChild(
+ id(new AphrontFormTextControl())
+ ->setLabel(pht('API Token'))
+ ->setValue($token->getToken()))
+ ->appendRemarkupInstructions(
+ pht(
+ 'This will authorize the requesting script to act on your behalf '.
+ 'permanently, like giving the script your account password.'))
+ ->appendRemarkupInstructions(
+ pht(
+ 'If you change your mind, you can revoke this token later in '.
+ '{nav icon=wrench,name=Settings > Conduit API Tokens}.'));
+
+ return $this->newDialog()
+ ->setTitle(pht('Grant Account Access'))
+ ->setWidth(AphrontDialogView::WIDTH_FULL)
+ ->appendForm($form)
+ ->addCancelButton('/');
+ }
+
+}
diff --git a/src/applications/conduit/method/ConduitGetCapabilitiesConduitAPIMethod.php b/src/applications/conduit/method/ConduitGetCapabilitiesConduitAPIMethod.php
new file mode 100644
--- /dev/null
+++ b/src/applications/conduit/method/ConduitGetCapabilitiesConduitAPIMethod.php
@@ -0,0 +1,60 @@
+<?php
+
+final class ConduitGetCapabilitiesConduitAPIMethod extends ConduitAPIMethod {
+
+ public function getAPIMethodName() {
+ return 'conduit.getcapabilities';
+ }
+
+ public function shouldRequireAuthentication() {
+ return false;
+ }
+
+ public function getMethodDescription() {
+ return pht(
+ 'List capabilities, wire formats, and authentication protocols '.
+ 'available on this server.');
+ }
+
+ public function defineParamTypes() {
+ return array();
+ }
+
+ public function defineReturnType() {
+ return 'dict<string, any>';
+ }
+
+ public function defineErrorTypes() {
+ return array();
+ }
+
+ protected function execute(ConduitAPIRequest $request) {
+ $authentication = array(
+ 'token',
+ 'asymmetric',
+ 'session',
+ 'sessionless',
+ );
+
+ $oauth_app = 'PhabricatorOAuthServerApplication';
+ if (PhabricatorApplication::isClassInstalled($oauth_app)) {
+ $authentication[] = 'oauth';
+ }
+
+ return array(
+ 'authentication' => $authentication,
+ 'signatures' => array(
+ 'consign',
+ ),
+ 'input' => array(
+ 'json',
+ 'urlencoded',
+ ),
+ 'output' => array(
+ 'json',
+ 'human',
+ ),
+ );
+ }
+
+}
diff --git a/src/applications/conduit/storage/PhabricatorConduitToken.php b/src/applications/conduit/storage/PhabricatorConduitToken.php
--- a/src/applications/conduit/storage/PhabricatorConduitToken.php
+++ b/src/applications/conduit/storage/PhabricatorConduitToken.php
@@ -13,6 +13,7 @@
const TYPE_STANDARD = 'api';
const TYPE_TEMPORARY = 'tmp';
+ const TYPE_COMMANDLINE = 'cli';
public function getConfiguration() {
return array(
@@ -53,17 +54,28 @@
$map = array(
self::TYPE_STANDARD => pht('Standard API Token'),
self::TYPE_TEMPORARY => pht('Temporary API Token'),
+ self::TYPE_COMMANDLINE => pht('Command Line API Token'),
);
return idx($map, $type, $type);
}
+ public static function getAllTokenTypes() {
+ return array(
+ self::TYPE_STANDARD,
+ self::TYPE_TEMPORARY,
+ self::TYPE_COMMANDLINE,
+ );
+ }
+
private function getTokenExpires($token_type) {
switch ($token_type) {
case self::TYPE_STANDARD:
return null;
case self::TYPE_TEMPORARY:
- return PhabricatorTime::getNow() + phutil_units('24h in seconds');
+ return PhabricatorTime::getNow() + phutil_units('24 hours in seconds');
+ case self::TYPE_COMMANDLINE:
+ return PhabricatorTime::getNow() + phutil_units('1 hour in seconds');
default:
throw new Exception(
pht('Unknown Conduit token type "%s"!', $token_type));

File Metadata

Mime Type
text/plain
Expires
Tue, Mar 4, 1:39 PM (10 h, 20 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7221800
Default Alt Text
D10989.diff (10 KB)

Event Timeline