mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-25 00:02:41 +01:00
PhabricatorEnv
'infratructure' -> 'infrastructure' (rofl) Recaptcha Email Login / Forgot Password Password Reset
This commit is contained in:
parent
25aae76c8a
commit
03fec6e911
62 changed files with 1418 additions and 104 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,3 +2,4 @@
|
|||
._*
|
||||
/docs/
|
||||
/src/.phutil_module_cache
|
||||
/conf/custom/*
|
||||
|
|
46
conf/default.conf.php
Normal file
46
conf/default.conf.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
return array(
|
||||
|
||||
// The root URI which Phabricator is installed on.
|
||||
// Example: "http://phabricator.example.com/"
|
||||
'phabricator.base-uri' => null,
|
||||
|
||||
|
||||
//
|
||||
'phabricator.csrf-key' => '0b7ec0592e0a2829d8b71df2fa269b2c6172eca3',
|
||||
|
||||
|
||||
// -- Facebook ---------------------------------------------------------------
|
||||
|
||||
// Can users use Facebook credentials to login to Phabricator?
|
||||
'facebook.auth-enabled' => false,
|
||||
|
||||
// The Facebook "Application ID" to use for Facebook API access.
|
||||
'facebook.application-id' => null,
|
||||
|
||||
// The Facebook "Application Secret" to use for Facebook API access.
|
||||
'facebook.application-secret' => null,
|
||||
|
||||
'recaptcha.public-key' => null,
|
||||
'recaptcha.private-key' => null,
|
||||
|
||||
|
||||
|
||||
);
|
22
conf/development.conf.php
Normal file
22
conf/development.conf.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
return array(
|
||||
|
||||
|
||||
) + phabricator_read_config_file('default');
|
23
conf/production.conf.php
Normal file
23
conf/production.conf.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
return array(
|
||||
|
||||
|
||||
) + phabricator_read_config_file('default');
|
||||
|
22
externals/recaptcha/LICENSE
vendored
Normal file
22
externals/recaptcha/LICENSE
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
|
||||
AUTHORS:
|
||||
Mike Crawford
|
||||
Ben Maurer
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
277
externals/recaptcha/recaptchalib.php
vendored
Normal file
277
externals/recaptcha/recaptchalib.php
vendored
Normal file
|
@ -0,0 +1,277 @@
|
|||
<?php
|
||||
/*
|
||||
* This is a PHP library that handles calling reCAPTCHA.
|
||||
* - Documentation and latest version
|
||||
* http://recaptcha.net/plugins/php/
|
||||
* - Get a reCAPTCHA API Key
|
||||
* https://www.google.com/recaptcha/admin/create
|
||||
* - Discussion group
|
||||
* http://groups.google.com/group/recaptcha
|
||||
*
|
||||
* Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
|
||||
* AUTHORS:
|
||||
* Mike Crawford
|
||||
* Ben Maurer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The reCAPTCHA server URL's
|
||||
*/
|
||||
define("RECAPTCHA_API_SERVER", "http://www.google.com/recaptcha/api");
|
||||
define("RECAPTCHA_API_SECURE_SERVER", "https://www.google.com/recaptcha/api");
|
||||
define("RECAPTCHA_VERIFY_SERVER", "www.google.com");
|
||||
|
||||
/**
|
||||
* Encodes the given data into a query string format
|
||||
* @param $data - array of string elements to be encoded
|
||||
* @return string - encoded request
|
||||
*/
|
||||
function _recaptcha_qsencode ($data) {
|
||||
$req = "";
|
||||
foreach ( $data as $key => $value )
|
||||
$req .= $key . '=' . urlencode( stripslashes($value) ) . '&';
|
||||
|
||||
// Cut the last '&'
|
||||
$req=substr($req,0,strlen($req)-1);
|
||||
return $req;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Submits an HTTP POST to a reCAPTCHA server
|
||||
* @param string $host
|
||||
* @param string $path
|
||||
* @param array $data
|
||||
* @param int port
|
||||
* @return array response
|
||||
*/
|
||||
function _recaptcha_http_post($host, $path, $data, $port = 80) {
|
||||
|
||||
$req = _recaptcha_qsencode ($data);
|
||||
|
||||
$http_request = "POST $path HTTP/1.0\r\n";
|
||||
$http_request .= "Host: $host\r\n";
|
||||
$http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
|
||||
$http_request .= "Content-Length: " . strlen($req) . "\r\n";
|
||||
$http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
|
||||
$http_request .= "\r\n";
|
||||
$http_request .= $req;
|
||||
|
||||
$response = '';
|
||||
if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
|
||||
die ('Could not open socket');
|
||||
}
|
||||
|
||||
fwrite($fs, $http_request);
|
||||
|
||||
while ( !feof($fs) )
|
||||
$response .= fgets($fs, 1160); // One TCP-IP packet
|
||||
fclose($fs);
|
||||
$response = explode("\r\n\r\n", $response, 2);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the challenge HTML (javascript and non-javascript version).
|
||||
* This is called from the browser, and the resulting reCAPTCHA HTML widget
|
||||
* is embedded within the HTML form it was called from.
|
||||
* @param string $pubkey A public key for reCAPTCHA
|
||||
* @param string $error The error given by reCAPTCHA (optional, default is null)
|
||||
* @param boolean $use_ssl Should the request be made over ssl? (optional, default is false)
|
||||
|
||||
* @return string - The HTML to be embedded in the user's form.
|
||||
*/
|
||||
function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false)
|
||||
{
|
||||
if ($pubkey == null || $pubkey == '') {
|
||||
die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
|
||||
}
|
||||
|
||||
if ($use_ssl) {
|
||||
$server = RECAPTCHA_API_SECURE_SERVER;
|
||||
} else {
|
||||
$server = RECAPTCHA_API_SERVER;
|
||||
}
|
||||
|
||||
$errorpart = "";
|
||||
if ($error) {
|
||||
$errorpart = "&error=" . $error;
|
||||
}
|
||||
return '<script type="text/javascript" src="'. $server . '/challenge?k=' . $pubkey . $errorpart . '"></script>
|
||||
|
||||
<noscript>
|
||||
<iframe src="'. $server . '/noscript?k=' . $pubkey . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/>
|
||||
<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
|
||||
<input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>
|
||||
</noscript>';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A ReCaptchaResponse is returned from recaptcha_check_answer()
|
||||
*/
|
||||
class ReCaptchaResponse {
|
||||
var $is_valid;
|
||||
var $error;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calls an HTTP POST function to verify if the user's guess was correct
|
||||
* @param string $privkey
|
||||
* @param string $remoteip
|
||||
* @param string $challenge
|
||||
* @param string $response
|
||||
* @param array $extra_params an array of extra variables to post to the server
|
||||
* @return ReCaptchaResponse
|
||||
*/
|
||||
function recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $extra_params = array())
|
||||
{
|
||||
if ($privkey == null || $privkey == '') {
|
||||
die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
|
||||
}
|
||||
|
||||
if ($remoteip == null || $remoteip == '') {
|
||||
die ("For security reasons, you must pass the remote ip to reCAPTCHA");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//discard spam submissions
|
||||
if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) {
|
||||
$recaptcha_response = new ReCaptchaResponse();
|
||||
$recaptcha_response->is_valid = false;
|
||||
$recaptcha_response->error = 'incorrect-captcha-sol';
|
||||
return $recaptcha_response;
|
||||
}
|
||||
|
||||
$response = _recaptcha_http_post (RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify",
|
||||
array (
|
||||
'privatekey' => $privkey,
|
||||
'remoteip' => $remoteip,
|
||||
'challenge' => $challenge,
|
||||
'response' => $response
|
||||
) + $extra_params
|
||||
);
|
||||
|
||||
$answers = explode ("\n", $response [1]);
|
||||
$recaptcha_response = new ReCaptchaResponse();
|
||||
|
||||
if (trim ($answers [0]) == 'true') {
|
||||
$recaptcha_response->is_valid = true;
|
||||
}
|
||||
else {
|
||||
$recaptcha_response->is_valid = false;
|
||||
$recaptcha_response->error = $answers [1];
|
||||
}
|
||||
return $recaptcha_response;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* gets a URL where the user can sign up for reCAPTCHA. If your application
|
||||
* has a configuration page where you enter a key, you should provide a link
|
||||
* using this function.
|
||||
* @param string $domain The domain where the page is hosted
|
||||
* @param string $appname The name of your application
|
||||
*/
|
||||
function recaptcha_get_signup_url ($domain = null, $appname = null) {
|
||||
return "https://www.google.com/recaptcha/admin/create?" . _recaptcha_qsencode (array ('domains' => $domain, 'app' => $appname));
|
||||
}
|
||||
|
||||
function _recaptcha_aes_pad($val) {
|
||||
$block_size = 16;
|
||||
$numpad = $block_size - (strlen ($val) % $block_size);
|
||||
return str_pad($val, strlen ($val) + $numpad, chr($numpad));
|
||||
}
|
||||
|
||||
/* Mailhide related code */
|
||||
|
||||
function _recaptcha_aes_encrypt($val,$ky) {
|
||||
if (! function_exists ("mcrypt_encrypt")) {
|
||||
die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.");
|
||||
}
|
||||
$mode=MCRYPT_MODE_CBC;
|
||||
$enc=MCRYPT_RIJNDAEL_128;
|
||||
$val=_recaptcha_aes_pad($val);
|
||||
return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
|
||||
}
|
||||
|
||||
|
||||
function _recaptcha_mailhide_urlbase64 ($x) {
|
||||
return strtr(base64_encode ($x), '+/', '-_');
|
||||
}
|
||||
|
||||
/* gets the reCAPTCHA Mailhide url for a given email, public key and private key */
|
||||
function recaptcha_mailhide_url($pubkey, $privkey, $email) {
|
||||
if ($pubkey == '' || $pubkey == null || $privkey == "" || $privkey == null) {
|
||||
die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " .
|
||||
"you can do so at <a href='http://www.google.com/recaptcha/mailhide/apikey'>http://www.google.com/recaptcha/mailhide/apikey</a>");
|
||||
}
|
||||
|
||||
|
||||
$ky = pack('H*', $privkey);
|
||||
$cryptmail = _recaptcha_aes_encrypt ($email, $ky);
|
||||
|
||||
return "http://www.google.com/recaptcha/mailhide/d?k=" . $pubkey . "&c=" . _recaptcha_mailhide_urlbase64 ($cryptmail);
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the parts of the email to expose to the user.
|
||||
* eg, given johndoe@example,com return ["john", "example.com"].
|
||||
* the email is then displayed as john...@example.com
|
||||
*/
|
||||
function _recaptcha_mailhide_email_parts ($email) {
|
||||
$arr = preg_split("/@/", $email );
|
||||
|
||||
if (strlen ($arr[0]) <= 4) {
|
||||
$arr[0] = substr ($arr[0], 0, 1);
|
||||
} else if (strlen ($arr[0]) <= 6) {
|
||||
$arr[0] = substr ($arr[0], 0, 3);
|
||||
} else {
|
||||
$arr[0] = substr ($arr[0], 0, 4);
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets html to display an email address given a public an private key.
|
||||
* to get a key, go to:
|
||||
*
|
||||
* http://www.google.com/recaptcha/mailhide/apikey
|
||||
*/
|
||||
function recaptcha_mailhide_html($pubkey, $privkey, $email) {
|
||||
$emailparts = _recaptcha_mailhide_email_parts ($email);
|
||||
$url = recaptcha_mailhide_url ($pubkey, $privkey, $email);
|
||||
|
||||
return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) .
|
||||
"' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
|
@ -25,6 +25,8 @@ phutil_register_library_map(array(
|
|||
'AphrontFormControl' => 'view/form/control/base',
|
||||
'AphrontFormFileControl' => 'view/form/control/file',
|
||||
'AphrontFormMarkupControl' => 'view/form/control/markup',
|
||||
'AphrontFormPasswordControl' => 'view/form/control/password',
|
||||
'AphrontFormRecaptchaControl' => 'view/form/control/recaptcha',
|
||||
'AphrontFormSelectControl' => 'view/form/control/select',
|
||||
'AphrontFormStaticControl' => 'view/form/control/static',
|
||||
'AphrontFormSubmitControl' => 'view/form/control/submit',
|
||||
|
@ -54,10 +56,10 @@ phutil_register_library_map(array(
|
|||
'AphrontURIMapper' => 'aphront/mapper',
|
||||
'AphrontView' => 'view/base',
|
||||
'AphrontWebpageResponse' => 'aphront/response/webpage',
|
||||
'CelerityAPI' => 'infratructure/celerity/api',
|
||||
'CelerityResourceController' => 'infratructure/celerity/controller',
|
||||
'CelerityResourceMap' => 'infratructure/celerity/map',
|
||||
'CelerityStaticResourceResponse' => 'infratructure/celerity/response',
|
||||
'CelerityAPI' => 'infrastructure/celerity/api',
|
||||
'CelerityResourceController' => 'infrastructure/celerity/controller',
|
||||
'CelerityResourceMap' => 'infrastructure/celerity/map',
|
||||
'CelerityStaticResourceResponse' => 'infrastructure/celerity/response',
|
||||
'ConduitAPIMethod' => 'applications/conduit/method/base',
|
||||
'ConduitAPIRequest' => 'applications/conduit/protocol/request',
|
||||
'ConduitAPI_conduit_connect_Method' => 'applications/conduit/method/conduit/connect',
|
||||
|
@ -105,7 +107,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialRevisionUpdateHistoryView' => 'applications/differential/view/revisionupdatehistory',
|
||||
'DifferentialRevisionViewController' => 'applications/differential/controller/revisionview',
|
||||
'DifferentialUnitStatus' => 'applications/differential/constants/unitstatus',
|
||||
'Javelin' => 'infratructure/javelin/api',
|
||||
'Javelin' => 'infrastructure/javelin/api',
|
||||
'LiskDAO' => 'storage/lisk/dao',
|
||||
'Phabricator404Controller' => 'applications/base/controller/404',
|
||||
'PhabricatorAuthController' => 'applications/auth/controller/base',
|
||||
|
@ -128,7 +130,11 @@ phutil_register_library_map(array(
|
|||
'PhabricatorDirectoryItemEditController' => 'applications/directory/controller/itemedit',
|
||||
'PhabricatorDirectoryItemListController' => 'applications/directory/controller/itemlist',
|
||||
'PhabricatorDirectoryMainController' => 'applications/directory/controller/main',
|
||||
'PhabricatorFacebookConnectController' => 'applications/auth/controller/facebookconnect',
|
||||
'PhabricatorEmailLoginController' => 'applications/auth/controller/email',
|
||||
'PhabricatorEmailTokenController' => 'applications/auth/controller/emailtoken',
|
||||
'PhabricatorEnv' => 'infrastructure/env',
|
||||
'PhabricatorFacebookAuthController' => 'applications/auth/controller/facebookauth',
|
||||
'PhabricatorFacebookAuthDiagnosticsController' => 'applications/auth/controller/facebookauth/diagnostics',
|
||||
'PhabricatorFile' => 'applications/files/storage/file',
|
||||
'PhabricatorFileController' => 'applications/files/controller/base',
|
||||
'PhabricatorFileDAO' => 'applications/files/storage/base',
|
||||
|
@ -176,9 +182,9 @@ phutil_register_library_map(array(
|
|||
array(
|
||||
'_qsprintf_check_scalar_type' => 'storage/qsprintf',
|
||||
'_qsprintf_check_type' => 'storage/qsprintf',
|
||||
'celerity_generate_unique_node_id' => 'infratructure/celerity/api',
|
||||
'celerity_register_resource_map' => 'infratructure/celerity/map',
|
||||
'javelin_render_tag' => 'infratructure/javelin/markup',
|
||||
'celerity_generate_unique_node_id' => 'infrastructure/celerity/api',
|
||||
'celerity_register_resource_map' => 'infrastructure/celerity/map',
|
||||
'javelin_render_tag' => 'infrastructure/javelin/markup',
|
||||
'phabricator_format_relative_time' => 'view/utils',
|
||||
'phabricator_format_timestamp' => 'view/utils',
|
||||
'phabricator_format_units_generic' => 'view/utils',
|
||||
|
@ -186,7 +192,7 @@ phutil_register_library_map(array(
|
|||
'queryfx' => 'storage/queryfx',
|
||||
'queryfx_all' => 'storage/queryfx',
|
||||
'queryfx_one' => 'storage/queryfx',
|
||||
'require_celerity_resource' => 'infratructure/celerity/api',
|
||||
'require_celerity_resource' => 'infrastructure/celerity/api',
|
||||
'vqsprintf' => 'storage/qsprintf',
|
||||
'vqueryfx' => 'storage/queryfx',
|
||||
'vqueryfx_all' => 'storage/queryfx',
|
||||
|
@ -207,6 +213,8 @@ phutil_register_library_map(array(
|
|||
'AphrontFormControl' => 'AphrontView',
|
||||
'AphrontFormFileControl' => 'AphrontFormControl',
|
||||
'AphrontFormMarkupControl' => 'AphrontFormControl',
|
||||
'AphrontFormPasswordControl' => 'AphrontFormControl',
|
||||
'AphrontFormRecaptchaControl' => 'AphrontFormControl',
|
||||
'AphrontFormSelectControl' => 'AphrontFormControl',
|
||||
'AphrontFormStaticControl' => 'AphrontFormControl',
|
||||
'AphrontFormSubmitControl' => 'AphrontFormControl',
|
||||
|
@ -285,7 +293,10 @@ phutil_register_library_map(array(
|
|||
'PhabricatorDirectoryItemEditController' => 'PhabricatorDirectoryController',
|
||||
'PhabricatorDirectoryItemListController' => 'PhabricatorDirectoryController',
|
||||
'PhabricatorDirectoryMainController' => 'PhabricatorDirectoryController',
|
||||
'PhabricatorFacebookConnectController' => 'PhabricatorAuthController',
|
||||
'PhabricatorEmailLoginController' => 'PhabricatorAuthController',
|
||||
'PhabricatorEmailTokenController' => 'PhabricatorAuthController',
|
||||
'PhabricatorFacebookAuthController' => 'PhabricatorAuthController',
|
||||
'PhabricatorFacebookAuthDiagnosticsController' => 'PhabricatorAuthController',
|
||||
'PhabricatorFile' => 'PhabricatorFileDAO',
|
||||
'PhabricatorFileController' => 'PhabricatorController',
|
||||
'PhabricatorFileDAO' => 'PhabricatorLiskDAO',
|
||||
|
|
|
@ -115,9 +115,16 @@ class AphrontDefaultApplicationConfiguration
|
|||
=> 'PhabricatorMetaMTAMailingListEditController',
|
||||
),
|
||||
|
||||
'/login/$' => 'PhabricatorLoginController',
|
||||
'/login/' => array(
|
||||
'$' => 'PhabricatorLoginController',
|
||||
'email/$' => 'PhabricatorEmailLoginController',
|
||||
'etoken/(?<token>\w+)/$' => 'PhabricatorEmailTokenController',
|
||||
),
|
||||
'/logout/$' => 'PhabricatorLogoutController',
|
||||
'/facebook-connect/$' => 'PhabricatorFacebookConnectController',
|
||||
'/facebook-auth/' => array(
|
||||
'$' => 'PhabricatorFacebookAuthController',
|
||||
'diagnose/$' => 'PhabricatorFacebookAuthDiagnosticsController',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,16 @@ class AphrontRequest {
|
|||
private $path;
|
||||
private $requestData;
|
||||
private $user;
|
||||
private $env;
|
||||
|
||||
final public function setEnvConfig(array $conf) {
|
||||
$this->env = $conf;
|
||||
return $this;
|
||||
}
|
||||
|
||||
final public function getEnvConfig($key, $default = null) {
|
||||
return idx($this->env, $key, $default);
|
||||
}
|
||||
|
||||
final public function __construct($host, $path) {
|
||||
$this->host = $host;
|
||||
|
@ -122,6 +132,4 @@ class AphrontRequest {
|
|||
return $this->user;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
|
||||
phutil_require_module('phabricator', 'aphront/response/base');
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
|
||||
|
||||
phutil_require_source('AphrontAjaxResponse.php');
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PhabricatorEmailLoginController extends PhabricatorAuthController {
|
||||
|
||||
public function shouldRequireLogin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
|
||||
$e_email = true;
|
||||
$e_captcha = true;
|
||||
$errors = array();
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$e_email = null;
|
||||
$e_captcha = 'Again';
|
||||
|
||||
$captcha_ok = AphrontFormRecaptchaControl::processCaptcha($request);
|
||||
if (!$captcha_ok) {
|
||||
$errors[] = "Captcha response is incorrect, try again.";
|
||||
$e_captcha = 'Invalid';
|
||||
}
|
||||
|
||||
$email = $request->getStr('email');
|
||||
if (!strlen($email)) {
|
||||
$errors[] = "You must provide an email address.";
|
||||
$e_email = 'Required';
|
||||
}
|
||||
|
||||
if (!$errors) {
|
||||
// NOTE: Don't validate the email unless the captcha is good; this makes
|
||||
// it expensive to fish for valid email addresses while giving the user
|
||||
// a better error if they goof their email.
|
||||
|
||||
$target_user = id(new PhabricatorUser())->loadOneWhere(
|
||||
'email = %s',
|
||||
$email);
|
||||
|
||||
if (!$target_user) {
|
||||
$errors[] = "There is no account associated with that email address.";
|
||||
$e_email = "Invalid";
|
||||
}
|
||||
|
||||
if (!$errors) {
|
||||
$etoken = $target_user->generateEmailToken();
|
||||
|
||||
$mail = new PhabricatorMetaMTAMail();
|
||||
$mail->setSubject('Phabricator Email Authentication');
|
||||
$mail->addTos(
|
||||
array(
|
||||
$target_user->getEmail(),
|
||||
));
|
||||
$mail->setBody(
|
||||
"blah blah blah ".
|
||||
PhabricatorEnv::getURI('/login/etoken/'.$etoken.'/').'?email='.phutil_escape_uri($target_user->getEmail()));
|
||||
$mail->save();
|
||||
|
||||
$view = new AphrontRequestFailureView();
|
||||
$view->setHeader('Check Your Email');
|
||||
$view->appendChild(
|
||||
'<p>An email has been sent with a link you can use to login.</p>');
|
||||
return $this->buildStandardPageResponse(
|
||||
$view,
|
||||
array(
|
||||
'title' => 'Email Sent',
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$email_auth = new AphrontFormView();
|
||||
$email_auth
|
||||
->setAction('/login/email/')
|
||||
->setUser($request->getUser())
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
->setLabel('Email')
|
||||
->setName('email')
|
||||
->setValue($request->getStr('email'))
|
||||
->setError($e_email))
|
||||
->appendChild(
|
||||
id(new AphrontFormRecaptchaControl())
|
||||
->setLabel('Captcha')
|
||||
->setError($e_captcha))
|
||||
->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->setValue('Send Email'));
|
||||
|
||||
$error_view = null;
|
||||
if ($errors) {
|
||||
$error_view = new AphrontErrorView();
|
||||
$error_view->setTitle('Login Error');
|
||||
$error_view->setErrors($errors);
|
||||
}
|
||||
|
||||
|
||||
$panel = new AphrontPanelView();
|
||||
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
|
||||
$panel->appendChild('<h1>Forgot Password / Email Login</h1>');
|
||||
$panel->appendChild($email_auth);
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
array(
|
||||
$error_view,
|
||||
$panel,
|
||||
),
|
||||
array(
|
||||
'title' => 'Create New Account',
|
||||
));
|
||||
}
|
||||
|
||||
}
|
24
src/applications/auth/controller/email/__init__.php
Normal file
24
src/applications/auth/controller/email/__init__.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/auth/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/metamta/storage/mail');
|
||||
phutil_require_module('phabricator', 'applications/people/storage/user');
|
||||
phutil_require_module('phabricator', 'infrastructure/env');
|
||||
phutil_require_module('phabricator', 'view/form/base');
|
||||
phutil_require_module('phabricator', 'view/form/control/recaptcha');
|
||||
phutil_require_module('phabricator', 'view/form/control/submit');
|
||||
phutil_require_module('phabricator', 'view/form/error');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
phutil_require_module('phabricator', 'view/page/failure');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorEmailLoginController.php');
|
|
@ -0,0 +1,137 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PhabricatorEmailTokenController extends PhabricatorAuthController {
|
||||
|
||||
private $token;
|
||||
|
||||
public function shouldRequireLogin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->token = $data['token'];
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
|
||||
$token = $this->token;
|
||||
$email = $request->getStr('email');
|
||||
|
||||
$target_user = id(new PhabricatorUser())->loadOneWhere(
|
||||
'email = %s',
|
||||
$email);
|
||||
|
||||
if (!$target_user || !$target_user->validateEmailToken($token)) {
|
||||
$view = new AphrontRequestFailureView();
|
||||
$view->setHeader('Unable to Login');
|
||||
$view->appendChild(
|
||||
'<p>The authentication information in the link you clicked is '.
|
||||
'invalid or out of date. Make sure you are copy-and-pasting the '.
|
||||
'entire link into your browser. You can try again, or request '.
|
||||
'a new email.</p>');
|
||||
$view->appendChild(
|
||||
'<div class="aphront-failure-continue">'.
|
||||
'<a class="button" href="/login/email/">Send Another Email</a>'.
|
||||
'</div>');
|
||||
return $this->buildStandardPageResponse(
|
||||
$view,
|
||||
array(
|
||||
'title' => 'Email Sent',
|
||||
));
|
||||
}
|
||||
|
||||
if ($request->getUser()->getPHID() != $target_user->getPHID()) {
|
||||
$session_key = $target_user->establishSession('web');
|
||||
$request->setCookie('phusr', $target_user->getUsername());
|
||||
$request->setCookie('phsid', $session_key);
|
||||
}
|
||||
|
||||
$errors = array();
|
||||
|
||||
$e_pass = true;
|
||||
$e_confirm = true;
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$e_pass = 'Error';
|
||||
$e_confirm = 'Error';
|
||||
|
||||
$pass = $request->getStr('password');
|
||||
$confirm = $request->getStr('confirm');
|
||||
|
||||
if (strlen($pass) < 3) {
|
||||
$errors[] = 'That password is ridiculously short.';
|
||||
}
|
||||
|
||||
if ($pass !== $confirm) {
|
||||
$errors[] = "Passwords do not match.";
|
||||
}
|
||||
|
||||
if (!$errors) {
|
||||
$target_user->setPassword($pass);
|
||||
$target_user->save();
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI('/');
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$error_view = new AphrontErrorView();
|
||||
$error_view->setTitle('Password Reset Failed');
|
||||
$error_view->setErrors($errors);
|
||||
} else {
|
||||
$error_view = null;
|
||||
}
|
||||
|
||||
$form = new AphrontFormView();
|
||||
$form
|
||||
->setUser($target_user)
|
||||
->setAction('/login/etoken/'.$token.'/')
|
||||
->addHiddenInput('email', $email)
|
||||
->appendChild(
|
||||
id(new AphrontFormPasswordControl())
|
||||
->setLabel('New Password')
|
||||
->setName('password')
|
||||
->setError($e_pass))
|
||||
->appendChild(
|
||||
id(new AphrontFormPasswordControl())
|
||||
->setLabel('Confirm Password')
|
||||
->setName('confirm')
|
||||
->setError($e_confirm))
|
||||
->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->setValue('Reset Password')
|
||||
->addCancelButton('/', 'Skip'));
|
||||
|
||||
$panel = new AphrontPanelView();
|
||||
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
|
||||
$panel->setHeader('Reset Password');
|
||||
$panel->appendChild($form);
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
array(
|
||||
$error_view,
|
||||
$panel,
|
||||
),
|
||||
array(
|
||||
'title' => 'Create New Account',
|
||||
));
|
||||
}
|
||||
|
||||
}
|
|
@ -8,15 +8,14 @@
|
|||
|
||||
phutil_require_module('phabricator', 'aphront/response/redirect');
|
||||
phutil_require_module('phabricator', 'applications/auth/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/files/storage/file');
|
||||
phutil_require_module('phabricator', 'applications/people/storage/user');
|
||||
phutil_require_module('phabricator', 'view/form/base');
|
||||
phutil_require_module('phabricator', 'view/form/control/submit');
|
||||
phutil_require_module('phabricator', 'view/form/error');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
phutil_require_module('phabricator', 'view/page/failure');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFacebookConnectController.php');
|
||||
phutil_require_source('PhabricatorEmailTokenController.php');
|
|
@ -16,31 +16,99 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PhabricatorFacebookConnectController extends PhabricatorAuthController {
|
||||
class PhabricatorFacebookAuthController extends PhabricatorAuthController {
|
||||
|
||||
public function shouldRequireLogin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$auth_enabled = PhabricatorEnv::getEnvConfig('facebook.auth-enabled');
|
||||
if (!$auth_enabled) {
|
||||
return new Aphront400Response();
|
||||
}
|
||||
|
||||
$diagnose_auth =
|
||||
'<a href="/facebook-auth/diagnose/" class="button green">'.
|
||||
'Diagnose Facebook Auth Problems'.
|
||||
'</a>';
|
||||
|
||||
$request = $this->getRequest();
|
||||
|
||||
if ($request->getStr('error')) {
|
||||
die("OMG ERROR");
|
||||
$view = new AphrontRequestFailureView();
|
||||
$view->setHeader('Facebook Auth Failed');
|
||||
$view->appendChild(
|
||||
'<p>'.
|
||||
'<strong>Description:</strong> '.
|
||||
phutil_escape_html($request->getStr('error_description')).
|
||||
'</p>');
|
||||
$view->appendChild(
|
||||
'<p>'.
|
||||
'<strong>Error:</strong> '.
|
||||
phutil_escape_html($request->getStr('error')).
|
||||
'</p>');
|
||||
$view->appendChild(
|
||||
'<p>'.
|
||||
'<strong>Error Reason:</strong> '.
|
||||
phutil_escape_html($request->getStr('error_reason')).
|
||||
'</p>');
|
||||
$view->appendChild(
|
||||
'<div class="aphront-failure-continue">'.
|
||||
'<a href="/login/" class="button">Continue</a>'.
|
||||
'</div>');
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
$view,
|
||||
array(
|
||||
'title' => 'Facebook Auth Failed',
|
||||
));
|
||||
}
|
||||
|
||||
$token = $request->getStr('token');
|
||||
if (!$token) {
|
||||
$app_id = PhabricatorEnv::getEnvConfig('facebook.application-id');
|
||||
$app_secret = PhabricatorEnv::getEnvConfig('facebook.application-secret');
|
||||
$redirect_uri = PhabricatorEnv::getURI('/facebook-auth/');
|
||||
|
||||
$code = $request->getStr('code');
|
||||
$auth_uri = 'https://graph.facebook.com/oauth/access_token'.
|
||||
'?client_id=184510521580034'.
|
||||
'&redirect_uri=http://local.aphront.com/facebook-connect/'.
|
||||
'&client_secret=OMGSECRETS'.
|
||||
'&code='.$code;
|
||||
$auth_uri = new PhutilURI(
|
||||
"https://graph.facebook.com/oauth/access_token");
|
||||
$auth_uri->setQueryParams(
|
||||
array(
|
||||
'client_id' => $app_id,
|
||||
'redirect_uri' => $redirect_uri,
|
||||
'client_secret' => $app_secret,
|
||||
'code' => $code,
|
||||
));
|
||||
|
||||
$response = @file_get_contents($auth_uri);
|
||||
if ($response === false) {
|
||||
throw new Exception('failed to open oauth thing');
|
||||
$view = new AphrontRequestFailureView();
|
||||
$view->setHeader('Facebook Auth Failed');
|
||||
$view->appendChild(
|
||||
'<p>Unable to authenticate with Facebook. There are several reasons '.
|
||||
'this might happen:</p>'.
|
||||
'<ul>'.
|
||||
'<li>Phabricator may be configured with the wrong Application '.
|
||||
'Secret; or</li>'.
|
||||
'<li>the Facebook OAuth access token may have expired; or</li>'.
|
||||
'<li>Facebook may have revoked authorization for the '.
|
||||
'Application; or</li>'.
|
||||
'<li>Facebook may be having technical problems.</li>'.
|
||||
'</ul>'.
|
||||
'<p>You can try again, or login using another method.</p>');
|
||||
$view->appendChild(
|
||||
'<div class="aphront-failure-continue">'.
|
||||
$diagnose_auth.
|
||||
'<a href="/login/" class="button">Continue</a>'.
|
||||
'</div>');
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
$view,
|
||||
array(
|
||||
'title' => 'Facebook Auth Failed',
|
||||
));
|
||||
}
|
||||
|
||||
$data = array();
|
||||
|
@ -89,12 +157,12 @@ class PhabricatorFacebookConnectController extends PhabricatorAuthController {
|
|||
$form
|
||||
->addHiddenInput('token', $token)
|
||||
->setUser($request->getUser())
|
||||
->setAction('/facebook-connect/')
|
||||
->setAction('/facebook-auth/')
|
||||
->appendChild(
|
||||
'<p class="aphront-form-view-instructions">Do you want to link your '.
|
||||
"existing Phabricator account (<strong>{$ph_account}</strong>) ".
|
||||
"with your Facebook account (<strong>{$fb_account}</strong>) so ".
|
||||
"you can login with Facebook Connect?")
|
||||
"you can login with Facebook?")
|
||||
->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->setValue('Link Accounts')
|
||||
|
@ -170,7 +238,7 @@ class PhabricatorFacebookConnectController extends PhabricatorAuthController {
|
|||
$error_view = null;
|
||||
if ($errors) {
|
||||
$error_view = new AphrontErrorView();
|
||||
$error_view->setTitle('Facebook Connect Failed');
|
||||
$error_view->setTitle('Facebook Auth Failed');
|
||||
$error_view->setErrors($errors);
|
||||
}
|
||||
|
||||
|
@ -178,7 +246,7 @@ class PhabricatorFacebookConnectController extends PhabricatorAuthController {
|
|||
$form
|
||||
->addHiddenInput('token', $token)
|
||||
->setUser($request->getUser())
|
||||
->setAction('/facebook-connect/')
|
||||
->setAction('/facebook-auth/')
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
->setLabel('Username')
|
25
src/applications/auth/controller/facebookauth/__init__.php
Normal file
25
src/applications/auth/controller/facebookauth/__init__.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'aphront/response/400');
|
||||
phutil_require_module('phabricator', 'aphront/response/redirect');
|
||||
phutil_require_module('phabricator', 'applications/auth/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/files/storage/file');
|
||||
phutil_require_module('phabricator', 'applications/people/storage/user');
|
||||
phutil_require_module('phabricator', 'infrastructure/env');
|
||||
phutil_require_module('phabricator', 'view/form/base');
|
||||
phutil_require_module('phabricator', 'view/form/control/submit');
|
||||
phutil_require_module('phabricator', 'view/form/error');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
phutil_require_module('phabricator', 'view/page/failure');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'parser/uri');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
phutil_require_source('PhabricatorFacebookAuthController.php');
|
|
@ -0,0 +1,230 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PhabricatorFacebookAuthDiagnosticsController
|
||||
extends PhabricatorAuthController {
|
||||
|
||||
public function shouldRequireLogin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
|
||||
$auth_enabled = PhabricatorEnv::getEnvConfig('facebook.auth-enabled');
|
||||
$app_id = PhabricatorEnv::getEnvConfig('facebook.application-id');
|
||||
$app_secret = PhabricatorEnv::getEnvConfig('facebook.application-secret');
|
||||
|
||||
$res_ok = '<strong style="color: #00aa00;">OK</strong>';
|
||||
$res_no = '<strong style="color: #aa0000;">NO</strong>';
|
||||
$res_na = '<strong style="color: #999999;">N/A</strong>';
|
||||
|
||||
$results = array();
|
||||
|
||||
if (!$auth_enabled) {
|
||||
$results['facebook.auth-enabled'] = array(
|
||||
$res_no,
|
||||
'false',
|
||||
'Facebook authentication is disabled in the configuration. Edit the '.
|
||||
'environmental configuration to enable "facebook.auth-enabled".');
|
||||
} else {
|
||||
$results['facebook.auth-enabled'] = array(
|
||||
$res_ok,
|
||||
'true',
|
||||
'Facebook authentication is enabled.');
|
||||
}
|
||||
|
||||
if (!$app_id) {
|
||||
$results['facebook.application-id'] = array(
|
||||
$res_no,
|
||||
null,
|
||||
'No Facebook Application ID is configured. Edit the environmental '.
|
||||
'configuration to specify an application ID in '.
|
||||
'"facebook.application-id". To generate an ID, sign into Facebook, '.
|
||||
'install the "Developer" application, and use it to create a new '.
|
||||
'Facebook application.');
|
||||
} else {
|
||||
$results['facebook.application-id'] = array(
|
||||
$res_ok,
|
||||
$app_id,
|
||||
'Application ID is set.');
|
||||
}
|
||||
|
||||
if (!$app_secret) {
|
||||
$results['facebook.application-secret'] = array(
|
||||
$res_no,
|
||||
null,
|
||||
'No Facebook Application secret is configured. Edit the environmental '.
|
||||
'configuration to specify an Application Secret, in '.
|
||||
'"facebook.application-secret". You can find the application secret '.
|
||||
'in the Facebook "Developer" application on Facebook.');
|
||||
} else {
|
||||
$results['facebook.application-secret'] = array(
|
||||
$res_ok,
|
||||
"It's a secret!",
|
||||
'Application secret is set.');
|
||||
}
|
||||
|
||||
$timeout = stream_context_create(
|
||||
array(
|
||||
'http' => array(
|
||||
'ignore_errors' => true,
|
||||
'timeout' => 5,
|
||||
),
|
||||
));
|
||||
$timeout_strict = stream_context_create(
|
||||
array(
|
||||
'http' => array(
|
||||
'timeout' => 5,
|
||||
),
|
||||
));
|
||||
|
||||
$internet = @file_get_contents("http://google.com/", false, $timeout);
|
||||
if ($internet === false) {
|
||||
$results['internet'] = array(
|
||||
$res_no,
|
||||
null,
|
||||
'Unable to make an HTTP request to Google. Check your outbound '.
|
||||
'internet connection and firewall/filtering settings.');
|
||||
} else {
|
||||
$results['internet'] = array(
|
||||
$res_ok,
|
||||
null,
|
||||
'Internet seems OK.');
|
||||
}
|
||||
|
||||
$facebook = @file_get_contents("http://facebook.com/", false, $timeout);
|
||||
if ($facebook === false) {
|
||||
$results['facebook.com'] = array(
|
||||
$res_no,
|
||||
null,
|
||||
'Unable to make an HTTP request to facebook.com. Facebook may be '.
|
||||
'down or inaccessible.');
|
||||
} else {
|
||||
$results['facebook.com'] = array(
|
||||
$res_ok,
|
||||
null,
|
||||
'Made a request to facebook.com.');
|
||||
}
|
||||
|
||||
$graph = @file_get_contents(
|
||||
"https://graph.facebook.com/me",
|
||||
false,
|
||||
$timeout);
|
||||
if ($graph === false) {
|
||||
$results['Facebook Graph'] = array(
|
||||
$res_no,
|
||||
null,
|
||||
"Unable to make an HTTPS request to graph.facebook.com. ".
|
||||
"The Facebook graph may be down or inaccessible.");
|
||||
} else {
|
||||
$results['Facebook Graph'] = array(
|
||||
$res_ok,
|
||||
null,
|
||||
'Made a request to graph.facebook.com.');
|
||||
}
|
||||
|
||||
$test_uri = new PhutilURI('https://graph.facebook.com/oauth/access_token');
|
||||
$test_uri->setQueryParams(
|
||||
array(
|
||||
'client_id' => $app_id,
|
||||
'client_secret' => $app_secret,
|
||||
'grant_type' => 'client_credentials',
|
||||
));
|
||||
|
||||
$token_value = @file_get_contents($test_uri, false, $timeout);
|
||||
$token_strict = @file_get_contents($test_uri, false, $timeout_strict);
|
||||
if ($token_value === false) {
|
||||
$results['App Login'] = array(
|
||||
$res_no,
|
||||
null,
|
||||
"Unable to perform an application login with your Application ID and ".
|
||||
"Application Secret. You may have mistyped or misconfigured them; ".
|
||||
"Facebook may have revoked your authorization; or Facebook may be ".
|
||||
"having technical problems.");
|
||||
} else {
|
||||
if ($token_strict) {
|
||||
$results['App Login'] = array(
|
||||
$res_ok,
|
||||
$token_strict,
|
||||
"Raw application login to Facebook works.");
|
||||
} else {
|
||||
$data = json_decode($token_value, true);
|
||||
if (!is_array($data)) {
|
||||
$results['App Login'] = array(
|
||||
$res_no,
|
||||
$token_value,
|
||||
"Application Login failed but the graph server did not respond ".
|
||||
"with valid JSON error information. Facebook may be experiencing ".
|
||||
"technical problems.");
|
||||
} else {
|
||||
$results['App Login'] = array(
|
||||
$res_no,
|
||||
null,
|
||||
"Application Login failed with error: ".$token_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->renderResults($results);
|
||||
}
|
||||
|
||||
private function renderResults($results) {
|
||||
|
||||
$rows = array();
|
||||
foreach ($results as $key => $result) {
|
||||
$rows[] = array(
|
||||
phutil_escape_html($key),
|
||||
$result[0],
|
||||
phutil_escape_html($result[1]),
|
||||
phutil_escape_html($result[2]),
|
||||
);
|
||||
}
|
||||
|
||||
$table_view = new AphrontTableView($rows);
|
||||
$table_view->setHeaders(
|
||||
array(
|
||||
'Test',
|
||||
'Result',
|
||||
'Value',
|
||||
'Details',
|
||||
));
|
||||
$table_view->setColumnClasses(
|
||||
array(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
'wide',
|
||||
));
|
||||
|
||||
$panel_view = new AphrontPanelView();
|
||||
$panel_view->setHeader('Facebook Auth Diagnostics');
|
||||
$panel_view->appendChild(
|
||||
'<p class="aphront-panel-instructions">These tests may be able to '.
|
||||
'help diagnose the root cause of problems you experience with '.
|
||||
'Facebook Authentication. Reload the page to run the tests again.</p>');
|
||||
$panel_view->appendChild($table_view);
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
$panel_view,
|
||||
array(
|
||||
'title' => 'Facebook Auth Diagnostics',
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/auth/controller/base');
|
||||
phutil_require_module('phabricator', 'infrastructure/env');
|
||||
phutil_require_module('phabricator', 'view/control/table');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'parser/uri');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFacebookAuthDiagnosticsController.php');
|
|
@ -34,9 +34,6 @@ class PhabricatorLoginController extends PhabricatorAuthController {
|
|||
'username = %s',
|
||||
$username);
|
||||
|
||||
$user->setPassword('asdf');
|
||||
$user->save();
|
||||
|
||||
$okay = false;
|
||||
if ($user) {
|
||||
if ($user->comparePassword($request->getStr('password'))) {
|
||||
|
@ -71,13 +68,15 @@ class PhabricatorLoginController extends PhabricatorAuthController {
|
|||
->setAction('/login/')
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
->setLabel('Username')
|
||||
->setLabel('Username/Email')
|
||||
->setName('username')
|
||||
->setValue($username))
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
id(new AphrontFormPasswordControl())
|
||||
->setLabel('Password')
|
||||
->setName('password'))
|
||||
->setName('password')
|
||||
->setCaption(
|
||||
'<a href="/login/email/">Forgot your password? / Email Login</a>'))
|
||||
->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->setValue('Login'));
|
||||
|
@ -88,27 +87,39 @@ class PhabricatorLoginController extends PhabricatorAuthController {
|
|||
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
|
||||
$panel->appendChild($form);
|
||||
|
||||
$fbauth_enabled = PhabricatorEnv::getEnvConfig('facebook.auth-enabled');
|
||||
if ($fbauth_enabled) {
|
||||
$auth_uri = new PhutilURI("https://www.facebook.com/dialog/oauth");
|
||||
|
||||
// TODO: Hardcoded junk
|
||||
$connect_uri = "https://www.facebook.com/dialog/oauth";
|
||||
$user = $request->getUser();
|
||||
|
||||
$user = $request->getUser();
|
||||
$redirect_uri = PhabricatorEnv::getURI('/facebook-auth/');
|
||||
$app_id = PhabricatorEnv::getEnvConfig('facebook.application-id');
|
||||
|
||||
$facebook_connect = new AphrontFormView();
|
||||
$facebook_connect
|
||||
->setAction($connect_uri)
|
||||
->addHiddenInput('client_id', 184510521580034)
|
||||
->addHiddenInput('redirect_uri', 'http://local.aphront.com/facebook-connect/')
|
||||
->addHiddenInput('scope', 'email')
|
||||
->addHiddenInput('state', $user->getCSRFToken())
|
||||
->setUser($request->getUser())
|
||||
->setMethod('GET')
|
||||
->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->setValue("Login with Facebook Connect \xC2\xBB"));
|
||||
// TODO: In theory we should use 'state' to prevent CSRF, but the total
|
||||
// effect of the CSRF attack is that an attacker can cause a user to login
|
||||
// to Phabricator if they're already logged into Facebook. This does not
|
||||
// seem like the most severe threat in the world, and generating CSRF for
|
||||
// logged-out users is vaugely tricky.
|
||||
|
||||
$panel->appendChild('<br /><h1>Login with Facebook</h1>');
|
||||
$panel->appendChild($facebook_connect);
|
||||
$facebook_auth = new AphrontFormView();
|
||||
$facebook_auth
|
||||
->setAction($auth_uri)
|
||||
->addHiddenInput('client_id', $app_id)
|
||||
->addHiddenInput('redirect_uri', $redirect_uri)
|
||||
->addHiddenInput('scope', 'email')
|
||||
->setUser($request->getUser())
|
||||
->setMethod('GET')
|
||||
->appendChild(
|
||||
'<p class="aphront-form-instructions">Login or register for '.
|
||||
'Phabricator using your Facebook account.</p>')
|
||||
->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->setValue("Login with Facebook \xC2\xBB"));
|
||||
|
||||
$panel->appendChild('<br /><h1>Login with Facebook</h1>');
|
||||
$panel->appendChild($facebook_auth);
|
||||
}
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
array(
|
||||
|
|
|
@ -9,11 +9,13 @@
|
|||
phutil_require_module('phabricator', 'aphront/response/redirect');
|
||||
phutil_require_module('phabricator', 'applications/auth/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/people/storage/user');
|
||||
phutil_require_module('phabricator', 'infrastructure/env');
|
||||
phutil_require_module('phabricator', 'view/form/base');
|
||||
phutil_require_module('phabricator', 'view/form/control/submit');
|
||||
phutil_require_module('phabricator', 'view/form/error');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
|
||||
phutil_require_module('phutil', 'parser/uri');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
phutil_require_module('phabricator', 'aphront/response/webpage');
|
||||
phutil_require_module('phabricator', 'applications/base/controller/base');
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infratructure/javelin/markup');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/javelin/markup');
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
|
||||
phutil_require_module('phabricator', 'applications/differential/constants/changetype');
|
||||
phutil_require_module('phabricator', 'applications/differential/view/changesetdetailview');
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infratructure/javelin/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/javelin/api');
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/differential/constants/changetype');
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/differential/constants/action');
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
phutil_require_module('phabricator', 'applications/differential/parser/markup');
|
||||
phutil_require_module('phabricator', 'applications/differential/view/revisioncomment');
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
phutil_require_module('phabricator', 'applications/directory/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/directory/storage/category');
|
||||
phutil_require_module('phabricator', 'applications/directory/storage/item');
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
|
|
@ -64,16 +64,23 @@ class PhabricatorUser extends PhabricatorUserDAO {
|
|||
return $password;
|
||||
}
|
||||
|
||||
const CSRF_CYCLE_FREQUENCY = 3600;
|
||||
const CSRF_CYCLE_FREQUENCY = 3600;
|
||||
const CSRF_TOKEN_LENGTH = 16;
|
||||
|
||||
public function getCSRFToken() {
|
||||
return $this->generateCSRFToken(time());
|
||||
const EMAIL_CYCLE_FREQUENCY = 86400;
|
||||
const EMAIL_TOKEN_LENGTH = 24;
|
||||
|
||||
public function getCSRFToken($offset = 0) {
|
||||
return $this->generateToken(
|
||||
time() + (self::CSRF_CYCLE_FREQUENCY * $offset),
|
||||
self::CSRF_CYCLE_FREQUENCY,
|
||||
PhabricatorEnv::getEnvConfig('phabricator.csrf-key'),
|
||||
self::CSRF_TOKEN_LENGTH);
|
||||
}
|
||||
|
||||
public function validateCSRFToken($token) {
|
||||
for ($ii = -1; $ii <= 1; $ii++) {
|
||||
$time = time() + (self::CSRF_CYCLE_FREQUENCY * $ii);
|
||||
$valid = $this->generateCSRFToken($time);
|
||||
$valid = $this->getCSRFToken($ii);
|
||||
if ($token == $valid) {
|
||||
return true;
|
||||
}
|
||||
|
@ -81,12 +88,10 @@ class PhabricatorUser extends PhabricatorUserDAO {
|
|||
return false;
|
||||
}
|
||||
|
||||
private function generateCSRFToken($epoch) {
|
||||
$time_block = floor($epoch / (60 * 60));
|
||||
// TODO: this should be a secret lolol
|
||||
$key = '0b7ec0592e0a2829d8b71df2fa269b2c6172eca3';
|
||||
private function generateToken($epoch, $frequency, $key, $len) {
|
||||
$time_block = floor($epoch / $frequency);
|
||||
$vec = $this->getPHID().$this->passwordHash.$key.$time_block;
|
||||
return substr(md5($vec), 0, 16);
|
||||
return substr(sha1($vec), 0, $len);
|
||||
}
|
||||
|
||||
public function establishSession($session_type) {
|
||||
|
@ -96,6 +101,7 @@ class PhabricatorUser extends PhabricatorUserDAO {
|
|||
if (!$urandom) {
|
||||
throw new Exception("Failed to open /dev/urandom!");
|
||||
}
|
||||
|
||||
$entropy = fread($urandom, 20);
|
||||
if (strlen($entropy) != 20) {
|
||||
throw new Exception("Failed to read /dev/urandom!");
|
||||
|
@ -118,4 +124,22 @@ class PhabricatorUser extends PhabricatorUserDAO {
|
|||
return $session_key;
|
||||
}
|
||||
|
||||
public function generateEmailToken($offset = 0) {
|
||||
return $this->generateToken(
|
||||
time() + ($offset * self::EMAIL_CYCLE_FREQUENCY),
|
||||
self::EMAIL_CYCLE_FREQUENCY,
|
||||
PhabricatorEnv::getEnvConfig('phabricator.csrf-key').$this->getEmail(),
|
||||
self::EMAIL_TOKEN_LENGTH);
|
||||
}
|
||||
|
||||
public function validateEmailToken($token) {
|
||||
for ($ii = -1; $ii <= 1; $ii++) {
|
||||
$valid = $this->generateEmailToken($ii);
|
||||
if ($token == $valid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
phutil_require_module('phabricator', 'applications/people/storage/base');
|
||||
phutil_require_module('phabricator', 'applications/phid/storage/phid');
|
||||
phutil_require_module('phabricator', 'infrastructure/env');
|
||||
phutil_require_module('phabricator', 'storage/queryfx');
|
||||
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/response');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/response');
|
||||
|
||||
|
||||
phutil_require_source('CelerityAPI.php');
|
|
@ -17,11 +17,11 @@
|
|||
*/
|
||||
|
||||
class CelerityResourceController extends AphrontController {
|
||||
|
||||
|
||||
private $path;
|
||||
private $hash;
|
||||
private $package;
|
||||
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->path = $data['path'];
|
||||
$this->hash = $data['hash'];
|
||||
|
@ -37,7 +37,7 @@ class CelerityResourceController extends AphrontController {
|
|||
if (!preg_match('/\.(css|js)$/', $path, $matches)) {
|
||||
throw new Exception("Only CSS and JS resources may be served.");
|
||||
}
|
||||
|
||||
|
||||
$type = $matches[1];
|
||||
|
||||
$root = dirname(phutil_get_library_root('phabricator'));
|
||||
|
@ -48,7 +48,7 @@ class CelerityResourceController extends AphrontController {
|
|||
if (!$paths) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
$data = array();
|
||||
foreach ($paths as $path) {
|
||||
|
@ -76,7 +76,7 @@ class CelerityResourceController extends AphrontController {
|
|||
$response->setMimeType("text/javascript; charset=utf-8");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
$response->setCacheDurationInSeconds(60 * 60 * 24 * 30);
|
||||
|
||||
return $response;
|
|
@ -7,7 +7,9 @@
|
|||
|
||||
|
||||
phutil_require_module('phabricator', 'aphront/controller');
|
||||
phutil_require_module('phabricator', 'aphront/response/404');
|
||||
phutil_require_module('phabricator', 'aphront/response/file');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/map');
|
||||
|
||||
phutil_require_module('phutil', 'filesystem');
|
||||
phutil_require_module('phutil', 'moduleutils');
|
|
@ -67,11 +67,11 @@ final class CelerityResourceMap {
|
|||
|
||||
$map[$symbol] = $info;
|
||||
}
|
||||
|
||||
|
||||
public function setPackageMap($package_map) {
|
||||
$this->packageMap = $package_map;
|
||||
}
|
||||
|
||||
|
||||
public function packageResources(array $resolved_map) {
|
||||
$packaged = array();
|
||||
$handled = array();
|
||||
|
@ -92,18 +92,18 @@ final class CelerityResourceMap {
|
|||
}
|
||||
return $packaged;
|
||||
}
|
||||
|
||||
|
||||
public function resolvePackage($package_hash) {
|
||||
$package = idx($this->packageMap['packages'], $package_hash);
|
||||
if (!$package) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
$paths = array();
|
||||
foreach ($package['symbols'] as $symbol) {
|
||||
$paths[] = $this->resourceMap[$symbol]['disk'];
|
||||
}
|
||||
|
||||
|
||||
return $paths;
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
|
||||
phutil_require_module('phutil', 'moduleutils');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('CelerityResourceMap.php');
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/map');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/map');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
34
src/infrastructure/env/PhabricatorEnv.php
vendored
Normal file
34
src/infrastructure/env/PhabricatorEnv.php
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhabricatorEnv {
|
||||
private static $env;
|
||||
|
||||
public static function setEnvConfig(array $config) {
|
||||
self::$env = $config;
|
||||
}
|
||||
|
||||
public static function getEnvConfig($key, $default = null) {
|
||||
return idx(self::$env, $key, $default);
|
||||
}
|
||||
|
||||
public static function getURI($path) {
|
||||
return rtrim(self::getEnvConfig('phabricator.base-uri'), '/').$path;
|
||||
}
|
||||
|
||||
}
|
12
src/infrastructure/env/__init__.php
vendored
Normal file
12
src/infrastructure/env/__init__.php
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorEnv.php');
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
|
||||
|
||||
phutil_require_source('Javelin.php');
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
|
|
@ -82,7 +82,15 @@ abstract class AphrontFormControl extends AphrontView {
|
|||
abstract protected function renderInput();
|
||||
abstract protected function getCustomControlClass();
|
||||
|
||||
protected function shouldRender() {
|
||||
return true;
|
||||
}
|
||||
|
||||
final public function render() {
|
||||
if (!$this->shouldRender()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$custom_class = $this->getCustomControlClass();
|
||||
|
||||
if (strlen($this->getLabel())) {
|
||||
|
@ -119,7 +127,7 @@ abstract class AphrontFormControl extends AphrontView {
|
|||
if (strlen($this->getCaption())) {
|
||||
$caption =
|
||||
'<div class="aphront-form-caption">'.
|
||||
phutil_escape_html($this->getCaption()).
|
||||
$this->getCaption().
|
||||
'</div>';
|
||||
} else {
|
||||
$caption = null;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'view/form/control/base');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
|
36
src/view/form/control/password/AphrontFormPasswordControl.php
Executable file
36
src/view/form/control/password/AphrontFormPasswordControl.php
Executable file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class AphrontFormPasswordControl extends AphrontFormControl {
|
||||
|
||||
protected function getCustomControlClass() {
|
||||
return 'aphront-form-control-password';
|
||||
}
|
||||
|
||||
protected function renderInput() {
|
||||
return phutil_render_tag(
|
||||
'input',
|
||||
array(
|
||||
'type' => 'password',
|
||||
'name' => $this->getName(),
|
||||
'value' => $this->getValue(),
|
||||
'disabled' => $this->getDisabled() ? 'disabled' : null,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
14
src/view/form/control/password/__init__.php
Normal file
14
src/view/form/control/password/__init__.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'view/form/control/base');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
||||
|
||||
phutil_require_source('AphrontFormPasswordControl.php');
|
65
src/view/form/control/recaptcha/AphrontFormRecaptchaControl.php
Executable file
65
src/view/form/control/recaptcha/AphrontFormRecaptchaControl.php
Executable file
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class AphrontFormRecaptchaControl extends AphrontFormControl {
|
||||
|
||||
protected function getCustomControlClass() {
|
||||
return 'aphront-form-control-recaptcha';
|
||||
}
|
||||
|
||||
protected function shouldRender() {
|
||||
return self::isRecaptchaEnabled();
|
||||
}
|
||||
|
||||
private static function isRecaptchaEnabled() {
|
||||
return PhabricatorEnv::getEnvConfig('recaptcha.enabled');
|
||||
}
|
||||
|
||||
private static function requireLib() {
|
||||
$root = phutil_get_library_root('phabricator');
|
||||
require_once dirname($root).'/externals/recaptcha/recaptchalib.php';
|
||||
}
|
||||
|
||||
public static function processCaptcha(AphrontRequest $request) {
|
||||
if (!self::isRecaptchaEnabled()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
self::requireLib();
|
||||
|
||||
$challenge = $request->getStr('recaptcha_challenge_field');
|
||||
$response = $request->getStr('recaptcha_response_field');
|
||||
$resp = recaptcha_check_answer(
|
||||
PhabricatorEnv::getEnvConfig('recaptcha.private-key'),
|
||||
$_SERVER['REMOTE_ADDR'],
|
||||
$challenge,
|
||||
$response);
|
||||
|
||||
return (bool)@$resp->is_valid;
|
||||
}
|
||||
|
||||
protected function renderInput() {
|
||||
self::requireLib();
|
||||
|
||||
return recaptcha_get_html(
|
||||
PhabricatorEnv::getEnvConfig('recaptcha.public-key'),
|
||||
$error = null,
|
||||
$use_ssl = false);
|
||||
}
|
||||
|
||||
}
|
15
src/view/form/control/recaptcha/__init__.php
Normal file
15
src/view/form/control/recaptcha/__init__.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infrastructure/env');
|
||||
phutil_require_module('phabricator', 'view/form/control/base');
|
||||
|
||||
phutil_require_module('phutil', 'moduleutils');
|
||||
|
||||
|
||||
phutil_require_source('AphrontFormRecaptchaControl.php');
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infratructure/javelin/api');
|
||||
phutil_require_module('phabricator', 'infratructure/javelin/markup');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/javelin/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/javelin/markup');
|
||||
phutil_require_module('phabricator', 'view/form/control/base');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
phutil_require_module('phabricator', 'view/null');
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infratructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'view/page/base');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
|
|
@ -16,8 +16,24 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
$env = getenv('PHABRICATOR_ENV');
|
||||
if (!$env) {
|
||||
header('Content-Type: text/plain');
|
||||
die(
|
||||
"CONFIG ERROR: ".
|
||||
"The 'PHABRICATOR_ENV' environmental variable is not defined. Modify ".
|
||||
"your httpd.conf to include 'SetEnv PHABRICATOR_ENV <env>', where '<env>' ".
|
||||
"is one of 'development', 'production', or a custom environment.");
|
||||
}
|
||||
|
||||
$conf = phabricator_read_config_file($env);
|
||||
$conf['phabricator.env'] = $env;
|
||||
|
||||
setup_aphront_basics();
|
||||
|
||||
phutil_require_module('phabricator', 'infrastructure/env');
|
||||
PhabricatorEnv::setEnvConfig($conf);
|
||||
|
||||
$host = $_SERVER['HTTP_HOST'];
|
||||
$path = $_REQUEST['__path__'];
|
||||
|
||||
|
@ -96,3 +112,14 @@ function setup_aphront_basics() {
|
|||
function __autoload($class_name) {
|
||||
PhutilSymbolLoader::loadClass($class_name);
|
||||
}
|
||||
|
||||
|
||||
function phabricator_read_config_file($config) {
|
||||
$root = dirname(dirname(__FILE__));
|
||||
$conf = include $root.'/conf/'.$config.'.conf.php';
|
||||
if ($conf === false) {
|
||||
throw new Exception("Failed to read config file '{$config}'.");
|
||||
}
|
||||
return $conf;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,4 +37,3 @@
|
|||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,9 +19,23 @@
|
|||
}
|
||||
|
||||
.aphront-request-failure-view .aphront-request-failure-body {
|
||||
padding: 1em 2em;
|
||||
padding: 1em 2em 1.5em;
|
||||
}
|
||||
|
||||
.aphront-request-failure-view .aphront-request-failure-body p {
|
||||
margin: .5em 0 1.25em;
|
||||
margin: .5em 0;
|
||||
}
|
||||
|
||||
.aphront-failure-continue {
|
||||
margin-top: 1.5em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.aphront-failure-continue a.button {
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.aphront-request-failure-view ul {
|
||||
list-style: disc;
|
||||
margin-left: 3em;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue