@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add a Duo API future

Summary: Depends on D20025. Ref T13231. Although I'm not currently planning to actually upstream a Duo MFA provider, it's probably easiest to put most of the support pieces in the upstream until T5055.

Test Plan: Used a test script to make some (mostly trivial) API calls and got valid results back, so I think the parameter signing is correct.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13231

Differential Revision: https://secure.phabricator.com/D20026

+153 -1
+2
src/__phutil_library_map__.php
··· 2983 2983 'PhabricatorDraftEngine' => 'applications/transactions/draft/PhabricatorDraftEngine.php', 2984 2984 'PhabricatorDraftInterface' => 'applications/transactions/draft/PhabricatorDraftInterface.php', 2985 2985 'PhabricatorDrydockApplication' => 'applications/drydock/application/PhabricatorDrydockApplication.php', 2986 + 'PhabricatorDuoFuture' => 'applications/auth/future/PhabricatorDuoFuture.php', 2986 2987 'PhabricatorEdgeChangeRecord' => 'infrastructure/edges/util/PhabricatorEdgeChangeRecord.php', 2987 2988 'PhabricatorEdgeChangeRecordTestCase' => 'infrastructure/edges/__tests__/PhabricatorEdgeChangeRecordTestCase.php', 2988 2989 'PhabricatorEdgeConfig' => 'infrastructure/edges/constants/PhabricatorEdgeConfig.php', ··· 8829 8830 'PhabricatorDraftDAO' => 'PhabricatorLiskDAO', 8830 8831 'PhabricatorDraftEngine' => 'Phobject', 8831 8832 'PhabricatorDrydockApplication' => 'PhabricatorApplication', 8833 + 'PhabricatorDuoFuture' => 'FutureProxy', 8832 8834 'PhabricatorEdgeChangeRecord' => 'Phobject', 8833 8835 'PhabricatorEdgeChangeRecordTestCase' => 'PhabricatorTestCase', 8834 8836 'PhabricatorEdgeConfig' => 'PhabricatorEdgeConstants',
+150
src/applications/auth/future/PhabricatorDuoFuture.php
··· 1 + <?php 2 + 3 + final class PhabricatorDuoFuture 4 + extends FutureProxy { 5 + 6 + private $future; 7 + 8 + private $integrationKey; 9 + private $secretKey; 10 + private $apiHostname; 11 + 12 + private $httpMethod = 'POST'; 13 + private $method; 14 + private $parameters; 15 + private $timeout; 16 + 17 + public function __construct() { 18 + parent::__construct(null); 19 + } 20 + 21 + public function setIntegrationKey($integration_key) { 22 + $this->integrationKey = $integration_key; 23 + return $this; 24 + } 25 + 26 + public function setSecretKey(PhutilOpaqueEnvelope $key) { 27 + $this->secretKey = $key; 28 + return $this; 29 + } 30 + 31 + public function setAPIHostname($hostname) { 32 + $this->apiHostname = $hostname; 33 + return $this; 34 + } 35 + 36 + public function setMethod($method, array $parameters) { 37 + $this->method = $method; 38 + $this->parameters = $parameters; 39 + return $this; 40 + } 41 + 42 + public function setTimeout($timeout) { 43 + $this->timeout = $timeout; 44 + return $this; 45 + } 46 + 47 + public function getTimeout() { 48 + return $this->timeout; 49 + } 50 + 51 + public function setHTTPMethod($method) { 52 + $this->httpMethod = $method; 53 + return $this; 54 + } 55 + 56 + public function getHTTPMethod() { 57 + return $this->httpMethod; 58 + } 59 + 60 + protected function getProxiedFuture() { 61 + if (!$this->future) { 62 + if ($this->integrationKey === null) { 63 + throw new PhutilInvalidStateException('setIntegrationKey'); 64 + } 65 + 66 + if ($this->secretKey === null) { 67 + throw new PhutilInvalidStateException('setSecretKey'); 68 + } 69 + 70 + if ($this->apiHostname === null) { 71 + throw new PhutilInvalidStateException('setAPIHostname'); 72 + } 73 + 74 + if ($this->method === null || $this->parameters === null) { 75 + throw new PhutilInvalidStateException('setMethod'); 76 + } 77 + 78 + $path = (string)urisprintf('/auth/v2/%s', $this->method); 79 + 80 + $host = $this->apiHostname; 81 + $host = phutil_utf8_strtolower($host); 82 + 83 + $uri = id(new PhutilURI('')) 84 + ->setProtocol('https') 85 + ->setDomain($host) 86 + ->setPath($path); 87 + 88 + $data = $this->parameters; 89 + $date = date('r'); 90 + 91 + $http_method = $this->getHTTPMethod(); 92 + 93 + ksort($data); 94 + $data_parts = array(); 95 + foreach ($data as $key => $value) { 96 + $data_parts[] = rawurlencode($key).'='.rawurlencode($value); 97 + } 98 + $data_parts = implode('&', $data_parts); 99 + 100 + $corpus = array( 101 + $date, 102 + $http_method, 103 + $host, 104 + $path, 105 + $data_parts, 106 + ); 107 + $corpus = implode("\n", $corpus); 108 + 109 + $signature = hash_hmac( 110 + 'sha1', 111 + $corpus, 112 + $this->secretKey->openEnvelope()); 113 + $signature = new PhutilOpaqueEnvelope($signature); 114 + 115 + $future = id(new HTTPSFuture($uri, $data)) 116 + ->setHTTPBasicAuthCredentials($this->integrationKey, $signature) 117 + ->setMethod($http_method) 118 + ->addHeader('Accept', 'application/json') 119 + ->addHeader('Date', $date); 120 + 121 + $timeout = $this->getTimeout(); 122 + if ($timeout) { 123 + $future->setTimeout($timeout); 124 + } 125 + 126 + $this->future = $future; 127 + } 128 + 129 + return $this->future; 130 + } 131 + 132 + protected function didReceiveResult($result) { 133 + list($status, $body, $headers) = $result; 134 + 135 + if ($status->isError()) { 136 + throw $status; 137 + } 138 + 139 + try { 140 + $data = phutil_json_decode($body); 141 + } catch (PhutilJSONParserException $ex) { 142 + throw new PhutilProxyException( 143 + pht('Expected JSON response from Duo.'), 144 + $ex); 145 + } 146 + 147 + return $data; 148 + } 149 + 150 + }
+1 -1
src/applications/metamta/future/PhabricatorTwilioFuture.php
··· 58 58 $this->accountSID, 59 59 $this->method); 60 60 61 - $uri = id(new PhutilURI('https://api.twilio.com/2010-04-01/accounts/')) 61 + $uri = id(new PhutilURI('https://api.twilio.com/')) 62 62 ->setPath($path); 63 63 64 64 $data = $this->parameters;