@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.

Basic Facebook OAuth implementation.

+357 -40
+7 -3
src/__phutil_library_map__.php
··· 39 39 'AphrontQueryConnectionException' => 'storage/exception/connection', 40 40 'AphrontQueryConnectionLostException' => 'storage/exception/connectionlost', 41 41 'AphrontQueryCountException' => 'storage/exception/count', 42 + 'AphrontQueryDuplicateKeyException' => 'storage/exception/duplicatekey', 42 43 'AphrontQueryException' => 'storage/exception/base', 43 44 'AphrontQueryObjectMissingException' => 'storage/exception/objectmissing', 44 45 'AphrontQueryParameterException' => 'storage/exception/parameter', ··· 107 108 'Javelin' => 'infratructure/javelin/api', 108 109 'LiskDAO' => 'storage/lisk/dao', 109 110 'Phabricator404Controller' => 'applications/base/controller/404', 110 - 'PhabricatorAuthController' => 'applications/auth/controlller/base', 111 + 'PhabricatorAuthController' => 'applications/auth/controller/base', 111 112 'PhabricatorConduitAPIController' => 'applications/conduit/controller/api', 112 113 'PhabricatorConduitConnectionLog' => 'applications/conduit/storage/connectionlog', 113 114 'PhabricatorConduitConsoleController' => 'applications/conduit/controller/console', ··· 127 128 'PhabricatorDirectoryItemEditController' => 'applications/directory/controller/itemedit', 128 129 'PhabricatorDirectoryItemListController' => 'applications/directory/controller/itemlist', 129 130 'PhabricatorDirectoryMainController' => 'applications/directory/controller/main', 131 + 'PhabricatorFacebookConnectController' => 'applications/auth/controller/facebookconnect', 130 132 'PhabricatorFile' => 'applications/files/storage/file', 131 133 'PhabricatorFileController' => 'applications/files/controller/base', 132 134 'PhabricatorFileDAO' => 'applications/files/storage/base', ··· 136 138 'PhabricatorFileUploadController' => 'applications/files/controller/upload', 137 139 'PhabricatorFileViewController' => 'applications/files/controller/view', 138 140 'PhabricatorLiskDAO' => 'applications/base/storage/lisk', 139 - 'PhabricatorLoginController' => 'applications/auth/controlller/login', 140 - 'PhabricatorLogoutController' => 'applications/auth/controlller/logout', 141 + 'PhabricatorLoginController' => 'applications/auth/controller/login', 142 + 'PhabricatorLogoutController' => 'applications/auth/controller/logout', 141 143 'PhabricatorMailImplementationAdapter' => 'applications/metamta/adapter/base', 142 144 'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/phpmailerlite', 143 145 'PhabricatorMetaMTAController' => 'applications/metamta/controller/base', ··· 219 221 'AphrontQueryConnectionException' => 'AphrontQueryException', 220 222 'AphrontQueryConnectionLostException' => 'AphrontQueryRecoverableException', 221 223 'AphrontQueryCountException' => 'AphrontQueryException', 224 + 'AphrontQueryDuplicateKeyException' => 'AphrontQueryException', 222 225 'AphrontQueryObjectMissingException' => 'AphrontQueryException', 223 226 'AphrontQueryParameterException' => 'AphrontQueryException', 224 227 'AphrontQueryRecoverableException' => 'AphrontQueryException', ··· 282 285 'PhabricatorDirectoryItemEditController' => 'PhabricatorDirectoryController', 283 286 'PhabricatorDirectoryItemListController' => 'PhabricatorDirectoryController', 284 287 'PhabricatorDirectoryMainController' => 'PhabricatorDirectoryController', 288 + 'PhabricatorFacebookConnectController' => 'PhabricatorAuthController', 285 289 'PhabricatorFile' => 'PhabricatorFileDAO', 286 290 'PhabricatorFileController' => 'PhabricatorController', 287 291 'PhabricatorFileDAO' => 'PhabricatorLiskDAO',
+3 -2
src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php
··· 115 115 => 'PhabricatorMetaMTAMailingListEditController', 116 116 ), 117 117 118 - '/login/' => 'PhabricatorLoginController', 119 - '/logout/' => 'PhabricatorLogoutController', 118 + '/login/$' => 'PhabricatorLoginController', 119 + '/logout/$' => 'PhabricatorLogoutController', 120 + '/facebook-connect/$' => 'PhabricatorFacebookConnectController', 120 121 ); 121 122 } 122 123
+207
src/applications/auth/controller/facebookconnect/PhabricatorFacebookConnectController.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2011 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + class PhabricatorFacebookConnectController extends PhabricatorAuthController { 20 + 21 + public function shouldRequireLogin() { 22 + return false; 23 + } 24 + 25 + public function processRequest() { 26 + $request = $this->getRequest(); 27 + 28 + if ($request->getStr('error')) { 29 + die("OMG ERROR"); 30 + } 31 + 32 + $token = $request->getStr('token'); 33 + if (!$token) { 34 + $code = $request->getStr('code'); 35 + $auth_uri = 'https://graph.facebook.com/oauth/access_token'. 36 + '?client_id=184510521580034'. 37 + '&redirect_uri=http://local.aphront.com/facebook-connect/'. 38 + '&client_secret=OMGSECRETS'. 39 + '&code='.$code; 40 + 41 + $response = @file_get_contents($auth_uri); 42 + if ($response === false) { 43 + throw new Exception('failed to open oauth thing'); 44 + } 45 + 46 + $data = array(); 47 + parse_str($response, $data); 48 + 49 + $token = $data['access_token']; 50 + } 51 + 52 + $user_json = @file_get_contents('https://graph.facebook.com/me?access_token='.$token); 53 + $user_data = json_decode($user_json, true); 54 + 55 + $user_id = $user_data['id']; 56 + 57 + $known_user = id(new PhabricatorUser()) 58 + ->loadOneWhere('facebookUID = %d', $user_id); 59 + if ($known_user) { 60 + $session_key = $known_user->establishSession('web'); 61 + $request->setCookie('phusr', $known_user->getUsername()); 62 + $request->setCookie('phsid', $session_key); 63 + return id(new AphrontRedirectResponse()) 64 + ->setURI('/'); 65 + } 66 + 67 + $current_user = $this->getRequest()->getUser(); 68 + if ($current_user->getPHID()) { 69 + if ($current_user->getFacebookUID() && 70 + $current_user->getFacebookUID() != $user_id) { 71 + throw new Exception( 72 + "Your account is already associated with a Facebook user ID other ". 73 + "than the one you just logged in with...?"); 74 + } 75 + 76 + if ($request->isFormPost()) { 77 + $current_user->setFacebookUID($user_id); 78 + $current_user->save(); 79 + 80 + // TODO: ship them back to the 'account' page or whatever? 81 + return id(new AphrontRedirectResponse()) 82 + ->setURI('/'); 83 + } 84 + 85 + $ph_account = $current_user->getUsername(); 86 + $fb_account = phutil_escape_html($user_data['name']); 87 + 88 + $form = new AphrontFormView(); 89 + $form 90 + ->addHiddenInput('token', $token) 91 + ->setUser($request->getUser()) 92 + ->setAction('/facebook-connect/') 93 + ->appendChild( 94 + '<p class="aphront-form-view-instructions">Do you want to link your '. 95 + "existing Phabricator account (<strong>{$ph_account}</strong>) ". 96 + "with your Facebook account (<strong>{$fb_account}</strong>) so ". 97 + "you can login with Facebook Connect?") 98 + ->appendChild( 99 + id(new AphrontFormSubmitControl()) 100 + ->setValue('Link Accounts') 101 + ->addCancelButton('/login/')); 102 + 103 + $panel = new AphrontPanelView(); 104 + $panel->setHeader('Link Facebook Account'); 105 + $panel->setWidth(AphrontPanelView::WIDTH_FORM); 106 + $panel->appendChild($form); 107 + 108 + return $this->buildStandardPageResponse( 109 + $panel, 110 + array( 111 + 'title' => 'Link Facebook Account', 112 + )); 113 + } 114 + 115 + $errors = array(); 116 + $e_username = true; 117 + 118 + $user = new PhabricatorUser(); 119 + 120 + $matches = null; 121 + if (preg_match('@/([a-zA-Z0-9]+)$@', $user_data['link'], $matches)) { 122 + $user->setUsername($matches[1]); 123 + } 124 + 125 + if ($request->isFormPost()) { 126 + 127 + $username = $request->getStr('username'); 128 + if (!strlen($username)) { 129 + $e_username = 'Required'; 130 + $errors[] = 'Username is required.'; 131 + } else if (!preg_match('/^[a-zA-Z0-9]+$/', $username, $matches)) { 132 + $e_username = 'Invalid'; 133 + $errors[] = 'Username may only contain letters and numbers.'; 134 + } 135 + 136 + $user->setUsername($username); 137 + $user->setFacebookUID($user_id); 138 + $user->setEmail($user_data['email']); 139 + 140 + if (!$errors) { 141 + $image = @file_get_contents('https://graph.facebook.com/me/picture?access_token='.$token); 142 + $file = PhabricatorFile::newFromFileData( 143 + $image, 144 + array( 145 + 'name' => 'fbprofile.jpg' 146 + )); 147 + 148 + $user->setProfileImagePHID($file->getPHID()); 149 + $user->setRealName($user_data['name']); 150 + 151 + try { 152 + $user->save(); 153 + 154 + $session_key = $user->establishSession('web'); 155 + $request->setCookie('phusr', $user->getUsername()); 156 + $request->setCookie('phsid', $session_key); 157 + return id(new AphrontRedirectResponse())->setURI('/'); 158 + } catch (AphrontQueryDuplicateKeyException $exception) { 159 + $key = $exception->getDuplicateKey(); 160 + if ($key == 'userName') { 161 + $e_username = 'Duplicate'; 162 + $errors[] = 'That username is not unique.'; 163 + } else { 164 + throw $exception; 165 + } 166 + } 167 + } 168 + } 169 + 170 + $error_view = null; 171 + if ($errors) { 172 + $error_view = new AphrontErrorView(); 173 + $error_view->setTitle('Facebook Connect Failed'); 174 + $error_view->setErrors($errors); 175 + } 176 + 177 + $form = new AphrontFormView(); 178 + $form 179 + ->addHiddenInput('token', $token) 180 + ->setUser($request->getUser()) 181 + ->setAction('/facebook-connect/') 182 + ->appendChild( 183 + id(new AphrontFormTextControl()) 184 + ->setLabel('Username') 185 + ->setName('username') 186 + ->setValue($user->getUsername()) 187 + ->setError($e_username)) 188 + ->appendChild( 189 + id(new AphrontFormSubmitControl()) 190 + ->setValue('Create Account')); 191 + 192 + $panel = new AphrontPanelView(); 193 + $panel->setHeader('Create New Account'); 194 + $panel->setWidth(AphrontPanelView::WIDTH_FORM); 195 + $panel->appendChild($form); 196 + 197 + return $this->buildStandardPageResponse( 198 + array( 199 + $error_view, 200 + $panel, 201 + ), 202 + array( 203 + 'title' => 'Create New Account', 204 + )); 205 + } 206 + 207 + }
+22
src/applications/auth/controller/facebookconnect/__init__.php
··· 1 + <?php 2 + /** 3 + * This file is automatically generated. Lint this module to rebuild it. 4 + * @generated 5 + */ 6 + 7 + 8 + 9 + phutil_require_module('phabricator', 'aphront/response/redirect'); 10 + phutil_require_module('phabricator', 'applications/auth/controller/base'); 11 + phutil_require_module('phabricator', 'applications/files/storage/file'); 12 + phutil_require_module('phabricator', 'applications/people/storage/user'); 13 + phutil_require_module('phabricator', 'view/form/base'); 14 + phutil_require_module('phabricator', 'view/form/control/submit'); 15 + phutil_require_module('phabricator', 'view/form/error'); 16 + phutil_require_module('phabricator', 'view/layout/panel'); 17 + 18 + phutil_require_module('phutil', 'markup'); 19 + phutil_require_module('phutil', 'utils'); 20 + 21 + 22 + phutil_require_source('PhabricatorFacebookConnectController.php');
src/applications/auth/controlller/base/PhabricatorAuthController.php src/applications/auth/controller/base/PhabricatorAuthController.php
src/applications/auth/controlller/base/__init__.php src/applications/auth/controller/base/__init__.php
+29 -29
src/applications/auth/controlller/login/PhabricatorLoginController.php src/applications/auth/controller/login/PhabricatorLoginController.php
··· 26 26 $request = $this->getRequest(); 27 27 28 28 $error = false; 29 - $login_name = $request->getCookie('phusr'); 29 + $username = $request->getCookie('phusr'); 30 30 if ($request->isFormPost()) { 31 - $login_name = $request->getStr('login'); 31 + $username = $request->getStr('username'); 32 32 33 33 $user = id(new PhabricatorUser())->loadOneWhere( 34 34 'username = %s', 35 - $login_name); 35 + $username); 36 36 37 37 $user->setPassword('asdf'); 38 38 $user->save(); ··· 40 40 $okay = false; 41 41 if ($user) { 42 42 if ($user->comparePassword($request->getStr('password'))) { 43 - $conn_w = $user->establishConnection('w'); 44 43 45 - $urandom = fopen('/dev/urandom', 'r'); 46 - if (!$urandom) { 47 - throw new Exception("Failed to open /dev/urandom!"); 48 - } 49 - $entropy = fread($urandom, 20); 50 - if (strlen($entropy) != 20) { 51 - throw new Exception("Failed to read /dev/urandom!"); 52 - } 53 - 54 - $session_key = sha1($entropy); 55 - queryfx( 56 - $conn_w, 57 - 'INSERT INTO phabricator_session '. 58 - '(userPHID, type, sessionKey, sessionStart)'. 59 - ' VALUES '. 60 - '(%s, %s, %s, UNIX_TIMESTAMP()) '. 61 - 'ON DUPLICATE KEY UPDATE '. 62 - 'sessionKey = VALUES(sessionKey), '. 63 - 'sessionStart = VALUES(sessionStart)', 64 - $user->getPHID(), 65 - 'web', 66 - $session_key); 44 + $session_key = $user->establishSession('web'); 67 45 68 46 $request->setCookie('phusr', $user->getUsername()); 69 47 $request->setCookie('phsid', $session_key); ··· 93 71 ->setAction('/login/') 94 72 ->appendChild( 95 73 id(new AphrontFormTextControl()) 96 - ->setLabel('Login') 97 - ->setName('login') 98 - ->setValue($login_name)) 74 + ->setLabel('Username') 75 + ->setName('username') 76 + ->setValue($username)) 99 77 ->appendChild( 100 78 id(new AphrontFormTextControl()) 101 79 ->setLabel('Password') ··· 109 87 $panel->setHeader('Phabricator Login'); 110 88 $panel->setWidth(AphrontPanelView::WIDTH_FORM); 111 89 $panel->appendChild($form); 90 + 91 + 92 + // TODO: Hardcoded junk 93 + $connect_uri = "https://www.facebook.com/dialog/oauth"; 94 + 95 + $user = $request->getUser(); 96 + 97 + $facebook_connect = new AphrontFormView(); 98 + $facebook_connect 99 + ->setAction($connect_uri) 100 + ->addHiddenInput('client_id', 184510521580034) 101 + ->addHiddenInput('redirect_uri', 'http://local.aphront.com/facebook-connect/') 102 + ->addHiddenInput('scope', 'email') 103 + ->addHiddenInput('state', $user->getCSRFToken()) 104 + ->setUser($request->getUser()) 105 + ->setMethod('GET') 106 + ->appendChild( 107 + id(new AphrontFormSubmitControl()) 108 + ->setValue("Login with Facebook Connect \xC2\xBB")); 109 + 110 + $panel->appendChild('<br /><h1>Login with Facebook</h1>'); 111 + $panel->appendChild($facebook_connect); 112 112 113 113 return $this->buildStandardPageResponse( 114 114 array(
+1 -2
src/applications/auth/controlller/login/__init__.php src/applications/auth/controller/login/__init__.php
··· 7 7 8 8 9 9 phutil_require_module('phabricator', 'aphront/response/redirect'); 10 - phutil_require_module('phabricator', 'applications/auth/controlller/base'); 10 + phutil_require_module('phabricator', 'applications/auth/controller/base'); 11 11 phutil_require_module('phabricator', 'applications/people/storage/user'); 12 - phutil_require_module('phabricator', 'storage/queryfx'); 13 12 phutil_require_module('phabricator', 'view/form/base'); 14 13 phutil_require_module('phabricator', 'view/form/control/submit'); 15 14 phutil_require_module('phabricator', 'view/form/error');
src/applications/auth/controlller/logout/PhabricatorLogoutController.php src/applications/auth/controller/logout/PhabricatorLogoutController.php
+1 -1
src/applications/auth/controlller/logout/__init__.php src/applications/auth/controller/logout/__init__.php
··· 7 7 8 8 9 9 phutil_require_module('phabricator', 'aphront/response/redirect'); 10 - phutil_require_module('phabricator', 'applications/auth/controlller/base'); 10 + phutil_require_module('phabricator', 'applications/auth/controller/base'); 11 11 12 12 phutil_require_module('phutil', 'utils'); 13 13
+31
src/applications/people/storage/user/PhabricatorUser.php
··· 26 26 protected $email; 27 27 protected $passwordSalt; 28 28 protected $passwordHash; 29 + protected $facebookUID; 30 + protected $profileImagePHID; 29 31 30 32 private $sessionKey; 31 33 ··· 85 87 $key = '0b7ec0592e0a2829d8b71df2fa269b2c6172eca3'; 86 88 $vec = $this->getPHID().$this->passwordHash.$key.$time_block; 87 89 return substr(md5($vec), 0, 16); 90 + } 91 + 92 + public function establishSession($session_type) { 93 + $conn_w = $this->establishConnection('w'); 94 + 95 + $urandom = fopen('/dev/urandom', 'r'); 96 + if (!$urandom) { 97 + throw new Exception("Failed to open /dev/urandom!"); 98 + } 99 + $entropy = fread($urandom, 20); 100 + if (strlen($entropy) != 20) { 101 + throw new Exception("Failed to read /dev/urandom!"); 102 + } 103 + 104 + $session_key = sha1($entropy); 105 + queryfx( 106 + $conn_w, 107 + 'INSERT INTO phabricator_session '. 108 + '(userPHID, type, sessionKey, sessionStart)'. 109 + ' VALUES '. 110 + '(%s, %s, %s, UNIX_TIMESTAMP()) '. 111 + 'ON DUPLICATE KEY UPDATE '. 112 + 'sessionKey = VALUES(sessionKey), '. 113 + 'sessionStart = VALUES(sessionStart)', 114 + $this->getPHID(), 115 + $session_type, 116 + $session_key); 117 + 118 + return $session_key; 88 119 } 89 120 90 121 }
+1
src/applications/people/storage/user/__init__.php
··· 8 8 9 9 phutil_require_module('phabricator', 'applications/people/storage/base'); 10 10 phutil_require_module('phabricator', 'applications/phid/storage/phid'); 11 + phutil_require_module('phabricator', 'storage/queryfx'); 11 12 12 13 13 14 phutil_require_source('PhabricatorUser.php');
+8 -3
src/storage/connection/mysql/AphrontMySQLDatabaseConnection.php
··· 184 184 case 2013: // Connection Dropped 185 185 case 2006: // Gone Away 186 186 throw new AphrontQueryConnectionLostException("#{$errno}: {$error}"); 187 - break; 188 187 case 1213: // Deadlock 189 188 case 1205: // Lock wait timeout exceeded 190 189 throw new AphrontQueryRecoverableException("#{$errno}: {$error}"); 191 - break; 190 + case 1062: // Duplicate Key 191 + $matches = null; 192 + $key = null; 193 + if (preg_match('/for key \'(.*)\'$/', $error, $matches)) { 194 + $key = $matches[1]; 195 + } 196 + throw new AphrontQueryDuplicateKeyException($key, "{$errno}: {$error}"); 192 197 default: 193 - // TODO: 1062 is syntax error, and quite terrible in production. 198 + // TODO: 1064 is syntax error, and quite terrible in production. 194 199 throw new AphrontQueryException("#{$errno}: {$error}"); 195 200 } 196 201 }
+1
src/storage/connection/mysql/__init__.php
··· 10 10 phutil_require_module('phabricator', 'storage/exception/base'); 11 11 phutil_require_module('phabricator', 'storage/exception/connection'); 12 12 phutil_require_module('phabricator', 'storage/exception/connectionlost'); 13 + phutil_require_module('phabricator', 'storage/exception/duplicatekey'); 13 14 phutil_require_module('phabricator', 'storage/exception/recoverable'); 14 15 15 16 phutil_require_module('phutil', 'utils');
+34
src/storage/exception/duplicatekey/AphrontQueryDuplicateKeyException.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2011 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + /** 20 + * @group storage 21 + */ 22 + class AphrontQueryDuplicateKeyException extends AphrontQueryException { 23 + 24 + private $duplicateKey; 25 + 26 + public function getDuplicateKey() { 27 + return $this->duplicateKey; 28 + } 29 + 30 + public function __construct($duplicate_key, $message) { 31 + $this->duplicateKey = $duplicate_key; 32 + parent::__construct($message); 33 + } 34 + }
+12
src/storage/exception/duplicatekey/__init__.php
··· 1 + <?php 2 + /** 3 + * This file is automatically generated. Lint this module to rebuild it. 4 + * @generated 5 + */ 6 + 7 + 8 + 9 + phutil_require_module('phabricator', 'storage/exception/base'); 10 + 11 + 12 + phutil_require_source('AphrontQueryDuplicateKeyException.php');