Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15280814
D10989.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
10 KB
Referenced Files
None
Subscribers
None
D10989.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
@@ -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
Details
Attached
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)
Attached To
Mode
D10989: Add conduit.getcapabilities and a modern CLI handshake workflow
Attached
Detach File
Event Timeline
Log In to Comment