diff --git a/resources/ircbot/example_config.json b/resources/ircbot/example_config.json index e909689e13..a310b74bb4 100644 --- a/resources/ircbot/example_config.json +++ b/resources/ircbot/example_config.json @@ -7,5 +7,9 @@ ], "handlers" : [ "PhabricatorIRCProtocolHandler" - ] + ], + + "conduit.uri" : null, + "conduit.user" : null, + "conduit.cert" : null } diff --git a/src/applications/people/controller/edit/PhabricatorPeopleEditController.php b/src/applications/people/controller/edit/PhabricatorPeopleEditController.php index 97d4290ebe..fba33053cb 100644 --- a/src/applications/people/controller/edit/PhabricatorPeopleEditController.php +++ b/src/applications/people/controller/edit/PhabricatorPeopleEditController.php @@ -48,6 +48,7 @@ class PhabricatorPeopleEditController extends PhabricatorPeopleController { 'basic' => 'Basic Information', 'password' => 'Reset Password', 'role' => 'Edit Role', + 'cert' => 'Conduit Certificate', ); if (!$user->getID()) { @@ -78,6 +79,9 @@ class PhabricatorPeopleEditController extends PhabricatorPeopleController { case 'role': $response = $this->processRoleRequest($user); break; + case 'cert': + $response = $this->processCertificateRequest($user); + break; } if ($response instanceof AphrontResponse) { @@ -376,4 +380,47 @@ class PhabricatorPeopleEditController extends PhabricatorPeopleController { return array($error_view, $panel); } + private function processCertificateRequest($user) { + $request = $this->getRequest(); + $admin = $request->getUser(); + + + $form = new AphrontFormView(); + $form + ->setUser($admin) + ->setAction($request->getRequestURI()) + ->appendChild( + '
You can use this certificate '. + 'to write scripts or bots which interface with Phabricator over '. + 'Conduit.
'); + + if ($user->getIsSystemAgent()) { + $form + ->appendChild( + id(new AphrontFormTextControl()) + ->setLabel('Username') + ->setValue($user->getUsername())) + ->appendChild( + id(new AphrontFormTextAreaControl()) + ->setLabel('Certificate') + ->setValue($user->getConduitCertificate())); + } else { + $form->appendChild( + id(new AphrontFormStaticControl()) + ->setLabel('Certificate') + ->setValue( + 'You may only view the certificates for System Agents. Mark '. + 'this account as a "system agent" in the "Edit Role" tab to '. + 'view the corresponding certificate.')); + } + + $panel = new AphrontPanelView(); + $panel->setHeader('Conduit Certificate'); + $panel->setWidth(AphrontPanelView::WIDTH_FORM); + + $panel->appendChild($form); + + return array($panel); + } + } diff --git a/src/applications/people/controller/edit/__init__.php b/src/applications/people/controller/edit/__init__.php index b689acf53d..742bbef230 100644 --- a/src/applications/people/controller/edit/__init__.php +++ b/src/applications/people/controller/edit/__init__.php @@ -12,8 +12,10 @@ phutil_require_module('phabricator', 'applications/people/controller/base'); phutil_require_module('phabricator', 'applications/people/storage/user'); phutil_require_module('phabricator', 'view/form/base'); phutil_require_module('phabricator', 'view/form/control/checkbox'); +phutil_require_module('phabricator', 'view/form/control/static'); phutil_require_module('phabricator', 'view/form/control/submit'); phutil_require_module('phabricator', 'view/form/control/text'); +phutil_require_module('phabricator', 'view/form/control/textarea'); phutil_require_module('phabricator', 'view/form/error'); phutil_require_module('phabricator', 'view/layout/panel'); phutil_require_module('phabricator', 'view/layout/sidenav'); diff --git a/src/infrastructure/daemon/irc/bot/PhabricatorIRCBot.php b/src/infrastructure/daemon/irc/bot/PhabricatorIRCBot.php index 8d5db14d92..605ead6ebc 100644 --- a/src/infrastructure/daemon/irc/bot/PhabricatorIRCBot.php +++ b/src/infrastructure/daemon/irc/bot/PhabricatorIRCBot.php @@ -34,6 +34,8 @@ final class PhabricatorIRCBot extends PhabricatorDaemon { private $writeBuffer; private $readBuffer; + private $conduit; + public function run() { $argv = $this->getArgv(); @@ -68,6 +70,25 @@ final class PhabricatorIRCBot extends PhabricatorDaemon { $this->handlers[] = $obj; } + $conduit_uri = idx($config, 'conduit.uri'); + if ($conduit_uri) { + $conduit_user = idx($config, 'conduit.user'); + $conduit_cert = idx($config, 'conduit.cert'); + + $conduit = new ConduitClient($conduit_uri); + $response = $conduit->callMethodSynchronous( + 'conduit.connect', + array( + 'client' => 'PhabricatorIRCBot', + 'clientVersion' => '1.0', + 'clientDescription' => php_uname('n').':'.$nick, + 'user' => $conduit_user, + 'certificate' => $conduit_cert, + )); + + $this->conduit = $conduit; + } + $errno = null; $error = null; $socket = fsockopen($server, $port, $errno, $error); @@ -130,7 +151,9 @@ final class PhabricatorIRCBot extends PhabricatorDaemon { } while (strlen($this->writeBuffer)); } - $this->processReadBuffer(); + do { + $routed_message = $this->processReadBuffer(); + } while ($routed_message); } while (true); } @@ -147,7 +170,7 @@ final class PhabricatorIRCBot extends PhabricatorDaemon { private function processReadBuffer() { $until = strpos($this->readBuffer, "\r\n"); if ($until === false) { - return; + return false; } $message = substr($this->readBuffer, 0, $until); @@ -171,6 +194,8 @@ final class PhabricatorIRCBot extends PhabricatorDaemon { $matches['data']); $this->routeMessage($irc_message); + + return true; } private function routeMessage(PhabricatorIRCMessage $message) { @@ -190,4 +215,13 @@ final class PhabricatorIRCBot extends PhabricatorDaemon { echo "\n"; } + public function getConduit() { + if (empty($this->conduit)) { + throw new Exception( + "This bot is not configured with a Conduit uplink. Set 'conduit.uri', ". + "'conduit.user' and 'conduit.cert' in the configuration to connect."); + } + return $this->conduit; + } + } diff --git a/src/infrastructure/daemon/irc/bot/__init__.php b/src/infrastructure/daemon/irc/bot/__init__.php index 2bad43e7d8..9c84970a76 100644 --- a/src/infrastructure/daemon/irc/bot/__init__.php +++ b/src/infrastructure/daemon/irc/bot/__init__.php @@ -9,6 +9,7 @@ phutil_require_module('phabricator', 'infrastructure/daemon/base'); phutil_require_module('phabricator', 'infrastructure/daemon/irc/message'); +phutil_require_module('phutil', 'conduit/client'); phutil_require_module('phutil', 'filesystem'); phutil_require_module('phutil', 'utils'); diff --git a/src/infrastructure/daemon/irc/handler/base/PhabricatorIRCHandler.php b/src/infrastructure/daemon/irc/handler/base/PhabricatorIRCHandler.php index 79d81302c1..755824273e 100644 --- a/src/infrastructure/daemon/irc/handler/base/PhabricatorIRCHandler.php +++ b/src/infrastructure/daemon/irc/handler/base/PhabricatorIRCHandler.php @@ -35,6 +35,10 @@ abstract class PhabricatorIRCHandler { return $this; } + final protected function getConduit() { + return $this->bot->getConduit(); + } + abstract public function receiveMessage(PhabricatorIRCMessage $message); }