mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 08:52:39 +01:00
Modularize Aphront "sites"
Summary: Fixes T5702. The path here is long and windy: - I want to move `blog.phacility.com` to the new `secure` host. - That host has `security.require-https` set, which I want to keep set (before, this was handled in a sort of hacky way at the nginx/preamble level, but I've cleaned up everything else now). - Currently, that setting forces blogs to HTTPS too, which won't work. - To let blogs be individually configurable, we need to either modularize site config or make things hackier. - Modularize rather than increasing hackiness. - Also add a little "modules" panel in Config. See T6859. This feels like a reasonable middle ground between putting this stuff in Applications and burying it in `bin/somewhere`. Test Plan: - Visited normal site. - Visited phame on-domain site. - Visited phame off-domain site. - Viewed static resources. {F561897} Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T5702 Differential Revision: https://secure.phabricator.com/D13474
This commit is contained in:
parent
12b966f44e
commit
6b7183a762
12 changed files with 358 additions and 77 deletions
|
@ -160,6 +160,7 @@ phutil_register_library_map(array(
|
||||||
'AphrontRequestTestCase' => 'aphront/__tests__/AphrontRequestTestCase.php',
|
'AphrontRequestTestCase' => 'aphront/__tests__/AphrontRequestTestCase.php',
|
||||||
'AphrontResponse' => 'aphront/response/AphrontResponse.php',
|
'AphrontResponse' => 'aphront/response/AphrontResponse.php',
|
||||||
'AphrontSideNavFilterView' => 'view/layout/AphrontSideNavFilterView.php',
|
'AphrontSideNavFilterView' => 'view/layout/AphrontSideNavFilterView.php',
|
||||||
|
'AphrontSite' => 'aphront/site/AphrontSite.php',
|
||||||
'AphrontStackTraceView' => 'view/widget/AphrontStackTraceView.php',
|
'AphrontStackTraceView' => 'view/widget/AphrontStackTraceView.php',
|
||||||
'AphrontStandaloneHTMLResponse' => 'aphront/response/AphrontStandaloneHTMLResponse.php',
|
'AphrontStandaloneHTMLResponse' => 'aphront/response/AphrontStandaloneHTMLResponse.php',
|
||||||
'AphrontTableView' => 'view/control/AphrontTableView.php',
|
'AphrontTableView' => 'view/control/AphrontTableView.php',
|
||||||
|
@ -1656,6 +1657,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorConfigSchemaQuery' => 'applications/config/schema/PhabricatorConfigSchemaQuery.php',
|
'PhabricatorConfigSchemaQuery' => 'applications/config/schema/PhabricatorConfigSchemaQuery.php',
|
||||||
'PhabricatorConfigSchemaSpec' => 'applications/config/schema/PhabricatorConfigSchemaSpec.php',
|
'PhabricatorConfigSchemaSpec' => 'applications/config/schema/PhabricatorConfigSchemaSpec.php',
|
||||||
'PhabricatorConfigServerSchema' => 'applications/config/schema/PhabricatorConfigServerSchema.php',
|
'PhabricatorConfigServerSchema' => 'applications/config/schema/PhabricatorConfigServerSchema.php',
|
||||||
|
'PhabricatorConfigSiteModuleController' => 'applications/config/controller/PhabricatorConfigSiteModuleController.php',
|
||||||
'PhabricatorConfigSiteSource' => 'infrastructure/env/PhabricatorConfigSiteSource.php',
|
'PhabricatorConfigSiteSource' => 'infrastructure/env/PhabricatorConfigSiteSource.php',
|
||||||
'PhabricatorConfigSource' => 'infrastructure/env/PhabricatorConfigSource.php',
|
'PhabricatorConfigSource' => 'infrastructure/env/PhabricatorConfigSource.php',
|
||||||
'PhabricatorConfigStackSource' => 'infrastructure/env/PhabricatorConfigStackSource.php',
|
'PhabricatorConfigStackSource' => 'infrastructure/env/PhabricatorConfigStackSource.php',
|
||||||
|
@ -2325,6 +2327,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorPhrequentConfigOptions' => 'applications/phrequent/config/PhabricatorPhrequentConfigOptions.php',
|
'PhabricatorPhrequentConfigOptions' => 'applications/phrequent/config/PhabricatorPhrequentConfigOptions.php',
|
||||||
'PhabricatorPhrictionApplication' => 'applications/phriction/application/PhabricatorPhrictionApplication.php',
|
'PhabricatorPhrictionApplication' => 'applications/phriction/application/PhabricatorPhrictionApplication.php',
|
||||||
'PhabricatorPhrictionConfigOptions' => 'applications/phriction/config/PhabricatorPhrictionConfigOptions.php',
|
'PhabricatorPhrictionConfigOptions' => 'applications/phriction/config/PhabricatorPhrictionConfigOptions.php',
|
||||||
|
'PhabricatorPlatformSite' => 'aphront/site/PhabricatorPlatformSite.php',
|
||||||
'PhabricatorPolicies' => 'applications/policy/constants/PhabricatorPolicies.php',
|
'PhabricatorPolicies' => 'applications/policy/constants/PhabricatorPolicies.php',
|
||||||
'PhabricatorPolicy' => 'applications/policy/storage/PhabricatorPolicy.php',
|
'PhabricatorPolicy' => 'applications/policy/storage/PhabricatorPolicy.php',
|
||||||
'PhabricatorPolicyApplication' => 'applications/policy/application/PhabricatorPolicyApplication.php',
|
'PhabricatorPolicyApplication' => 'applications/policy/application/PhabricatorPolicyApplication.php',
|
||||||
|
@ -2522,6 +2525,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorRepositoryURITestCase' => 'applications/repository/storage/__tests__/PhabricatorRepositoryURITestCase.php',
|
'PhabricatorRepositoryURITestCase' => 'applications/repository/storage/__tests__/PhabricatorRepositoryURITestCase.php',
|
||||||
'PhabricatorRepositoryVCSPassword' => 'applications/repository/storage/PhabricatorRepositoryVCSPassword.php',
|
'PhabricatorRepositoryVCSPassword' => 'applications/repository/storage/PhabricatorRepositoryVCSPassword.php',
|
||||||
'PhabricatorRepositoryVersion' => 'applications/repository/constants/PhabricatorRepositoryVersion.php',
|
'PhabricatorRepositoryVersion' => 'applications/repository/constants/PhabricatorRepositoryVersion.php',
|
||||||
|
'PhabricatorResourceSite' => 'aphront/site/PhabricatorResourceSite.php',
|
||||||
'PhabricatorRobotsController' => 'applications/system/controller/PhabricatorRobotsController.php',
|
'PhabricatorRobotsController' => 'applications/system/controller/PhabricatorRobotsController.php',
|
||||||
'PhabricatorS3FileStorageEngine' => 'applications/files/engine/PhabricatorS3FileStorageEngine.php',
|
'PhabricatorS3FileStorageEngine' => 'applications/files/engine/PhabricatorS3FileStorageEngine.php',
|
||||||
'PhabricatorSMS' => 'infrastructure/sms/storage/PhabricatorSMS.php',
|
'PhabricatorSMS' => 'infrastructure/sms/storage/PhabricatorSMS.php',
|
||||||
|
@ -2611,6 +2615,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSetupIssue' => 'applications/config/issue/PhabricatorSetupIssue.php',
|
'PhabricatorSetupIssue' => 'applications/config/issue/PhabricatorSetupIssue.php',
|
||||||
'PhabricatorSetupIssueUIExample' => 'applications/uiexample/examples/PhabricatorSetupIssueUIExample.php',
|
'PhabricatorSetupIssueUIExample' => 'applications/uiexample/examples/PhabricatorSetupIssueUIExample.php',
|
||||||
'PhabricatorSetupIssueView' => 'applications/config/view/PhabricatorSetupIssueView.php',
|
'PhabricatorSetupIssueView' => 'applications/config/view/PhabricatorSetupIssueView.php',
|
||||||
|
'PhabricatorSite' => 'aphront/site/PhabricatorSite.php',
|
||||||
'PhabricatorSlowvoteApplication' => 'applications/slowvote/application/PhabricatorSlowvoteApplication.php',
|
'PhabricatorSlowvoteApplication' => 'applications/slowvote/application/PhabricatorSlowvoteApplication.php',
|
||||||
'PhabricatorSlowvoteChoice' => 'applications/slowvote/storage/PhabricatorSlowvoteChoice.php',
|
'PhabricatorSlowvoteChoice' => 'applications/slowvote/storage/PhabricatorSlowvoteChoice.php',
|
||||||
'PhabricatorSlowvoteCloseController' => 'applications/slowvote/controller/PhabricatorSlowvoteCloseController.php',
|
'PhabricatorSlowvoteCloseController' => 'applications/slowvote/controller/PhabricatorSlowvoteCloseController.php',
|
||||||
|
@ -2889,6 +2894,8 @@ phutil_register_library_map(array(
|
||||||
'PhameBlogListController' => 'applications/phame/controller/blog/PhameBlogListController.php',
|
'PhameBlogListController' => 'applications/phame/controller/blog/PhameBlogListController.php',
|
||||||
'PhameBlogLiveController' => 'applications/phame/controller/blog/PhameBlogLiveController.php',
|
'PhameBlogLiveController' => 'applications/phame/controller/blog/PhameBlogLiveController.php',
|
||||||
'PhameBlogQuery' => 'applications/phame/query/PhameBlogQuery.php',
|
'PhameBlogQuery' => 'applications/phame/query/PhameBlogQuery.php',
|
||||||
|
'PhameBlogResourceSite' => 'applications/phame/site/PhameBlogResourceSite.php',
|
||||||
|
'PhameBlogSite' => 'applications/phame/site/PhameBlogSite.php',
|
||||||
'PhameBlogSkin' => 'applications/phame/skins/PhameBlogSkin.php',
|
'PhameBlogSkin' => 'applications/phame/skins/PhameBlogSkin.php',
|
||||||
'PhameBlogTransaction' => 'applications/phame/storage/PhameBlogTransaction.php',
|
'PhameBlogTransaction' => 'applications/phame/storage/PhameBlogTransaction.php',
|
||||||
'PhameBlogViewController' => 'applications/phame/controller/blog/PhameBlogViewController.php',
|
'PhameBlogViewController' => 'applications/phame/controller/blog/PhameBlogViewController.php',
|
||||||
|
@ -2917,6 +2924,7 @@ phutil_register_library_map(array(
|
||||||
'PhameQueryPostsConduitAPIMethod' => 'applications/phame/conduit/PhameQueryPostsConduitAPIMethod.php',
|
'PhameQueryPostsConduitAPIMethod' => 'applications/phame/conduit/PhameQueryPostsConduitAPIMethod.php',
|
||||||
'PhameResourceController' => 'applications/phame/controller/PhameResourceController.php',
|
'PhameResourceController' => 'applications/phame/controller/PhameResourceController.php',
|
||||||
'PhameSchemaSpec' => 'applications/phame/storage/PhameSchemaSpec.php',
|
'PhameSchemaSpec' => 'applications/phame/storage/PhameSchemaSpec.php',
|
||||||
|
'PhameSite' => 'applications/phame/site/PhameSite.php',
|
||||||
'PhameSkinSpecification' => 'applications/phame/skins/PhameSkinSpecification.php',
|
'PhameSkinSpecification' => 'applications/phame/skins/PhameSkinSpecification.php',
|
||||||
'PhluxController' => 'applications/phlux/controller/PhluxController.php',
|
'PhluxController' => 'applications/phlux/controller/PhluxController.php',
|
||||||
'PhluxDAO' => 'applications/phlux/storage/PhluxDAO.php',
|
'PhluxDAO' => 'applications/phlux/storage/PhluxDAO.php',
|
||||||
|
@ -3523,6 +3531,7 @@ phutil_register_library_map(array(
|
||||||
'AphrontRequestTestCase' => 'PhabricatorTestCase',
|
'AphrontRequestTestCase' => 'PhabricatorTestCase',
|
||||||
'AphrontResponse' => 'Phobject',
|
'AphrontResponse' => 'Phobject',
|
||||||
'AphrontSideNavFilterView' => 'AphrontView',
|
'AphrontSideNavFilterView' => 'AphrontView',
|
||||||
|
'AphrontSite' => 'Phobject',
|
||||||
'AphrontStackTraceView' => 'AphrontView',
|
'AphrontStackTraceView' => 'AphrontView',
|
||||||
'AphrontStandaloneHTMLResponse' => 'AphrontHTMLResponse',
|
'AphrontStandaloneHTMLResponse' => 'AphrontHTMLResponse',
|
||||||
'AphrontTableView' => 'AphrontView',
|
'AphrontTableView' => 'AphrontView',
|
||||||
|
@ -5263,6 +5272,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorConfigSchemaQuery' => 'Phobject',
|
'PhabricatorConfigSchemaQuery' => 'Phobject',
|
||||||
'PhabricatorConfigSchemaSpec' => 'Phobject',
|
'PhabricatorConfigSchemaSpec' => 'Phobject',
|
||||||
'PhabricatorConfigServerSchema' => 'PhabricatorConfigStorageSchema',
|
'PhabricatorConfigServerSchema' => 'PhabricatorConfigStorageSchema',
|
||||||
|
'PhabricatorConfigSiteModuleController' => 'PhabricatorConfigController',
|
||||||
'PhabricatorConfigSiteSource' => 'PhabricatorConfigProxySource',
|
'PhabricatorConfigSiteSource' => 'PhabricatorConfigProxySource',
|
||||||
'PhabricatorConfigSource' => 'Phobject',
|
'PhabricatorConfigSource' => 'Phobject',
|
||||||
'PhabricatorConfigStackSource' => 'PhabricatorConfigSource',
|
'PhabricatorConfigStackSource' => 'PhabricatorConfigSource',
|
||||||
|
@ -6022,6 +6032,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorPhrequentConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
'PhabricatorPhrequentConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||||
'PhabricatorPhrictionApplication' => 'PhabricatorApplication',
|
'PhabricatorPhrictionApplication' => 'PhabricatorApplication',
|
||||||
'PhabricatorPhrictionConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
'PhabricatorPhrictionConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||||
|
'PhabricatorPlatformSite' => 'PhabricatorSite',
|
||||||
'PhabricatorPolicies' => 'PhabricatorPolicyConstants',
|
'PhabricatorPolicies' => 'PhabricatorPolicyConstants',
|
||||||
'PhabricatorPolicy' => array(
|
'PhabricatorPolicy' => array(
|
||||||
'PhabricatorPolicyDAO',
|
'PhabricatorPolicyDAO',
|
||||||
|
@ -6290,6 +6301,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorRepositoryURITestCase' => 'PhabricatorTestCase',
|
'PhabricatorRepositoryURITestCase' => 'PhabricatorTestCase',
|
||||||
'PhabricatorRepositoryVCSPassword' => 'PhabricatorRepositoryDAO',
|
'PhabricatorRepositoryVCSPassword' => 'PhabricatorRepositoryDAO',
|
||||||
'PhabricatorRepositoryVersion' => 'Phobject',
|
'PhabricatorRepositoryVersion' => 'Phobject',
|
||||||
|
'PhabricatorResourceSite' => 'PhabricatorSite',
|
||||||
'PhabricatorRobotsController' => 'PhabricatorController',
|
'PhabricatorRobotsController' => 'PhabricatorController',
|
||||||
'PhabricatorS3FileStorageEngine' => 'PhabricatorFileStorageEngine',
|
'PhabricatorS3FileStorageEngine' => 'PhabricatorFileStorageEngine',
|
||||||
'PhabricatorSMS' => 'PhabricatorSMSDAO',
|
'PhabricatorSMS' => 'PhabricatorSMSDAO',
|
||||||
|
@ -6381,6 +6393,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSetupIssue' => 'Phobject',
|
'PhabricatorSetupIssue' => 'Phobject',
|
||||||
'PhabricatorSetupIssueUIExample' => 'PhabricatorUIExample',
|
'PhabricatorSetupIssueUIExample' => 'PhabricatorUIExample',
|
||||||
'PhabricatorSetupIssueView' => 'AphrontView',
|
'PhabricatorSetupIssueView' => 'AphrontView',
|
||||||
|
'PhabricatorSite' => 'AphrontSite',
|
||||||
'PhabricatorSlowvoteApplication' => 'PhabricatorApplication',
|
'PhabricatorSlowvoteApplication' => 'PhabricatorApplication',
|
||||||
'PhabricatorSlowvoteChoice' => 'PhabricatorSlowvoteDAO',
|
'PhabricatorSlowvoteChoice' => 'PhabricatorSlowvoteDAO',
|
||||||
'PhabricatorSlowvoteCloseController' => 'PhabricatorSlowvoteController',
|
'PhabricatorSlowvoteCloseController' => 'PhabricatorSlowvoteController',
|
||||||
|
@ -6705,6 +6718,8 @@ phutil_register_library_map(array(
|
||||||
'PhameBlogListController' => 'PhameController',
|
'PhameBlogListController' => 'PhameController',
|
||||||
'PhameBlogLiveController' => 'PhameController',
|
'PhameBlogLiveController' => 'PhameController',
|
||||||
'PhameBlogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'PhameBlogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
|
'PhameBlogResourceSite' => 'PhameSite',
|
||||||
|
'PhameBlogSite' => 'PhameSite',
|
||||||
'PhameBlogSkin' => 'PhabricatorController',
|
'PhameBlogSkin' => 'PhabricatorController',
|
||||||
'PhameBlogTransaction' => 'PhabricatorApplicationTransaction',
|
'PhameBlogTransaction' => 'PhabricatorApplicationTransaction',
|
||||||
'PhameBlogViewController' => 'PhameController',
|
'PhameBlogViewController' => 'PhameController',
|
||||||
|
@ -6739,6 +6754,7 @@ phutil_register_library_map(array(
|
||||||
'PhameQueryPostsConduitAPIMethod' => 'PhameConduitAPIMethod',
|
'PhameQueryPostsConduitAPIMethod' => 'PhameConduitAPIMethod',
|
||||||
'PhameResourceController' => 'CelerityResourceController',
|
'PhameResourceController' => 'CelerityResourceController',
|
||||||
'PhameSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
'PhameSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
||||||
|
'PhameSite' => 'PhabricatorSite',
|
||||||
'PhameSkinSpecification' => 'Phobject',
|
'PhameSkinSpecification' => 'Phobject',
|
||||||
'PhluxController' => 'PhabricatorController',
|
'PhluxController' => 'PhabricatorController',
|
||||||
'PhluxDAO' => 'PhabricatorLiskDAO',
|
'PhluxDAO' => 'PhabricatorLiskDAO',
|
||||||
|
|
|
@ -350,7 +350,9 @@ abstract class AphrontApplicationConfiguration extends Phobject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PhabricatorEnv::getEnvConfig('security.require-https')) {
|
$site = $this->buildSiteForRequest($request);
|
||||||
|
|
||||||
|
if ($site->shouldRequireHTTPS()) {
|
||||||
if (!$request->isHTTPS()) {
|
if (!$request->isHTTPS()) {
|
||||||
$https_uri = $request->getRequestURI();
|
$https_uri = $request->getRequestURI();
|
||||||
$https_uri->setDomain($request->getHost());
|
$https_uri->setDomain($request->getHost());
|
||||||
|
@ -362,82 +364,9 @@ abstract class AphrontApplicationConfiguration extends Phobject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$path = $request->getPath();
|
// TODO: Really, the Site should get more control here and be able to
|
||||||
$host = $request->getHost();
|
// do its own routing logic if it wants, but we don't need that for now.
|
||||||
$base_uri = PhabricatorEnv::getEnvConfig('phabricator.base-uri');
|
$path = $site->getPathForRouting($request);
|
||||||
$prod_uri = PhabricatorEnv::getEnvConfig('phabricator.production-uri');
|
|
||||||
$file_uri = PhabricatorEnv::getEnvConfig(
|
|
||||||
'security.alternate-file-domain');
|
|
||||||
$allowed_uris = PhabricatorEnv::getEnvConfig('phabricator.allowed-uris');
|
|
||||||
|
|
||||||
$uris = array_merge(
|
|
||||||
array(
|
|
||||||
$base_uri,
|
|
||||||
$prod_uri,
|
|
||||||
),
|
|
||||||
$allowed_uris);
|
|
||||||
|
|
||||||
$cdn_routes = array(
|
|
||||||
'/res/',
|
|
||||||
'/file/data/',
|
|
||||||
'/file/xform/',
|
|
||||||
'/phame/r/',
|
|
||||||
);
|
|
||||||
|
|
||||||
$host_match = false;
|
|
||||||
foreach ($uris as $uri) {
|
|
||||||
if ($host === id(new PhutilURI($uri))->getDomain()) {
|
|
||||||
$host_match = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$host_match) {
|
|
||||||
if ($host === id(new PhutilURI($file_uri))->getDomain()) {
|
|
||||||
foreach ($cdn_routes as $route) {
|
|
||||||
if (strncmp($path, $route, strlen($route)) == 0) {
|
|
||||||
$host_match = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: If the base URI isn't defined yet, don't activate alternate
|
|
||||||
// domains.
|
|
||||||
if ($base_uri && !$host_match) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
$blog = id(new PhameBlogQuery())
|
|
||||||
->setViewer(new PhabricatorUser())
|
|
||||||
->withDomain($host)
|
|
||||||
->executeOne();
|
|
||||||
} catch (PhabricatorPolicyException $ex) {
|
|
||||||
throw new Exception(
|
|
||||||
pht(
|
|
||||||
'This blog is not visible to logged out users, so it can not be '.
|
|
||||||
'visited from a custom domain.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$blog) {
|
|
||||||
if ($prod_uri && $prod_uri != $base_uri) {
|
|
||||||
$prod_str = pht('%s or %s', $base_uri, $prod_uri);
|
|
||||||
} else {
|
|
||||||
$prod_str = $base_uri;
|
|
||||||
}
|
|
||||||
throw new Exception(
|
|
||||||
pht(
|
|
||||||
'Specified domain %s is not configured for Phabricator '.
|
|
||||||
'requests. Please use %s to visit this instance.',
|
|
||||||
$host,
|
|
||||||
$prod_str));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Make this more flexible and modular so any application can
|
|
||||||
// do crazy stuff here if it wants.
|
|
||||||
|
|
||||||
$path = '/phame/live/'.$blog->getID().'/'.$path;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($controller, $uri_data) = $this->buildControllerForPath($path);
|
list($controller, $uri_data) = $this->buildControllerForPath($path);
|
||||||
if (!$controller) {
|
if (!$controller) {
|
||||||
|
@ -509,4 +438,29 @@ abstract class AphrontApplicationConfiguration extends Phobject {
|
||||||
return array($controller, $uri_data);
|
return array($controller, $uri_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function buildSiteForRequest(AphrontRequest $request) {
|
||||||
|
$sites = PhabricatorSite::getAllSites();
|
||||||
|
|
||||||
|
$site = null;
|
||||||
|
foreach ($sites as $candidate) {
|
||||||
|
$site = $candidate->newSiteForRequest($request);
|
||||||
|
if ($site) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$site) {
|
||||||
|
$path = $request->getPath();
|
||||||
|
$host = $request->getHost();
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'This request asked for "%s" on host "%s", but no site is '.
|
||||||
|
'configured which can serve this request.',
|
||||||
|
$path,
|
||||||
|
$host));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $site;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
52
src/aphront/site/AphrontSite.php
Normal file
52
src/aphront/site/AphrontSite.php
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class AphrontSite extends Phobject {
|
||||||
|
|
||||||
|
abstract public function getPriority();
|
||||||
|
abstract public function getDescription();
|
||||||
|
|
||||||
|
abstract public function shouldRequireHTTPS();
|
||||||
|
abstract public function newSiteForRequest(AphrontRequest $request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NOTE: This is temporary glue; eventually, sites will return an entire
|
||||||
|
* route map.
|
||||||
|
*/
|
||||||
|
public function getPathForRouting(AphrontRequest $request) {
|
||||||
|
return $request->getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function isHostMatch($host, array $uris) {
|
||||||
|
foreach ($uris as $uri) {
|
||||||
|
if (!strlen($uri)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$domain = id(new PhutilURI($uri))->getDomain();
|
||||||
|
|
||||||
|
if ($domain === $host) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function isPathPrefixMatch($path, array $paths) {
|
||||||
|
foreach ($paths as $candidate) {
|
||||||
|
if (strncmp($path, $candidate, strlen($candidate)) === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public static function getAllSites() {
|
||||||
|
return id(new PhutilClassMapQuery())
|
||||||
|
->setAncestorClass(__CLASS__)
|
||||||
|
->setSortMethod('getPriority')
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
33
src/aphront/site/PhabricatorPlatformSite.php
Normal file
33
src/aphront/site/PhabricatorPlatformSite.php
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorPlatformSite extends PhabricatorSite {
|
||||||
|
|
||||||
|
public function getDescription() {
|
||||||
|
return pht('Serves the core platform and applications.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPriority() {
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newSiteForRequest(AphrontRequest $request) {
|
||||||
|
$uris = array();
|
||||||
|
$uris[] = PhabricatorEnv::getEnvConfig('phabricator.base-uri');
|
||||||
|
$uris[] = PhabricatorEnv::getEnvConfig('phabricator.production-uri');
|
||||||
|
|
||||||
|
$allowed = PhabricatorEnv::getEnvConfig('phabricator.allowed-uris');
|
||||||
|
if ($allowed) {
|
||||||
|
foreach ($allowed as $uri) {
|
||||||
|
$uris[] = $uri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$host = $request->getHost();
|
||||||
|
if ($this->isHostMatch($host, $uris)) {
|
||||||
|
return new PhabricatorPlatformSite();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
41
src/aphront/site/PhabricatorResourceSite.php
Normal file
41
src/aphront/site/PhabricatorResourceSite.php
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorResourceSite extends PhabricatorSite {
|
||||||
|
|
||||||
|
public function getDescription() {
|
||||||
|
return pht('Serves static resources like images, CSS and JS.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPriority() {
|
||||||
|
return 2000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newSiteForRequest(AphrontRequest $request) {
|
||||||
|
$host = $request->getHost();
|
||||||
|
|
||||||
|
$uri = PhabricatorEnv::getEnvConfig('security.alternate-file-domain');
|
||||||
|
if (!strlen($uri)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->isHostMatch($host, array($uri))) {
|
||||||
|
return new PhabricatorResourceSite();
|
||||||
|
}
|
||||||
|
|
||||||
|
// These are CDN routes, so we let them through even if the "Host" header
|
||||||
|
// doesn't match anything we recognize. The
|
||||||
|
$whitelist = array(
|
||||||
|
'/res/',
|
||||||
|
'/file/data/',
|
||||||
|
'/file/xform/',
|
||||||
|
);
|
||||||
|
|
||||||
|
$path = $request->getPath();
|
||||||
|
if ($this->isPathPrefixMatch($path, $whitelist)) {
|
||||||
|
return new PhabricatorResourceSite();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
9
src/aphront/site/PhabricatorSite.php
Normal file
9
src/aphront/site/PhabricatorSite.php
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class PhabricatorSite extends AphrontSite {
|
||||||
|
|
||||||
|
public function shouldRequireHTTPS() {
|
||||||
|
return PhabricatorEnv::getEnvConfig('security.require-https');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -56,6 +56,9 @@ final class PhabricatorConfigApplication extends PhabricatorApplication {
|
||||||
'(?P<key>[^/]+)/' => 'PhabricatorConfigIssueViewController',
|
'(?P<key>[^/]+)/' => 'PhabricatorConfigIssueViewController',
|
||||||
),
|
),
|
||||||
'cache/' => 'PhabricatorConfigCacheController',
|
'cache/' => 'PhabricatorConfigCacheController',
|
||||||
|
'module/' => array(
|
||||||
|
'sites/' => 'PhabricatorConfigSiteModuleController',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,8 @@ abstract class PhabricatorConfigController extends PhabricatorController {
|
||||||
$nav->addFilter('cache/', pht('Cache Status'));
|
$nav->addFilter('cache/', pht('Cache Status'));
|
||||||
$nav->addLabel(pht('Welcome'));
|
$nav->addLabel(pht('Welcome'));
|
||||||
$nav->addFilter('welcome/', pht('Welcome Screen'));
|
$nav->addFilter('welcome/', pht('Welcome Screen'));
|
||||||
|
$nav->addLabel(pht('Modules'));
|
||||||
|
$nav->addFilter('module/sites/', pht('Sites'));
|
||||||
|
|
||||||
return $nav;
|
return $nav;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorConfigSiteModuleController
|
||||||
|
extends PhabricatorConfigController {
|
||||||
|
|
||||||
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$sites = AphrontSite::getAllSites();
|
||||||
|
|
||||||
|
$rows = array();
|
||||||
|
foreach ($sites as $key => $site) {
|
||||||
|
$rows[] = array(
|
||||||
|
$site->getPriority(),
|
||||||
|
$key,
|
||||||
|
$site->getDescription(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = id(new AphrontTableView($rows))
|
||||||
|
->setHeaders(
|
||||||
|
array(
|
||||||
|
pht('Priority'),
|
||||||
|
pht('Class'),
|
||||||
|
pht('Description'),
|
||||||
|
))
|
||||||
|
->setColumnClasses(
|
||||||
|
array(
|
||||||
|
null,
|
||||||
|
'pri',
|
||||||
|
'wide',
|
||||||
|
));
|
||||||
|
|
||||||
|
$box = id(new PHUIObjectBoxView())
|
||||||
|
->setHeaderText(pht('Site Modules'))
|
||||||
|
->appendChild($table);
|
||||||
|
|
||||||
|
$crumbs = $this->buildApplicationCrumbs();
|
||||||
|
$crumbs->addTextCrumb(pht('Site Modules'));
|
||||||
|
|
||||||
|
$nav = $this->buildSideNavView();
|
||||||
|
$nav->selectFilter('module/sites/');
|
||||||
|
$nav->appendChild(
|
||||||
|
array(
|
||||||
|
$crumbs,
|
||||||
|
$box,
|
||||||
|
));
|
||||||
|
|
||||||
|
return $this->buildApplicationPage(
|
||||||
|
$nav,
|
||||||
|
array(
|
||||||
|
'title' => array(pht('Site Modules')),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
30
src/applications/phame/site/PhameBlogResourceSite.php
Normal file
30
src/applications/phame/site/PhameBlogResourceSite.php
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhameBlogResourceSite extends PhameSite {
|
||||||
|
|
||||||
|
public function getDescription() {
|
||||||
|
return pht('Serves static resources for blogs.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPriority() {
|
||||||
|
return 3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newSiteForRequest(AphrontRequest $request) {
|
||||||
|
if (!$this->isPhameActive()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$whitelist = array(
|
||||||
|
'/phame/r/',
|
||||||
|
);
|
||||||
|
|
||||||
|
$path = $request->getPath();
|
||||||
|
if (!$this->isPathPrefixMatch($path, $whitelist)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PhameBlogResourceSite();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
63
src/applications/phame/site/PhameBlogSite.php
Normal file
63
src/applications/phame/site/PhameBlogSite.php
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhameBlogSite extends PhameSite {
|
||||||
|
|
||||||
|
private $blog;
|
||||||
|
|
||||||
|
public function setBlog(PhameBlog $blog) {
|
||||||
|
$this->blog = $blog;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBlog() {
|
||||||
|
return $this->blog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDescription() {
|
||||||
|
return pht('Serves blogs with custom domains.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldRequireHTTPS() {
|
||||||
|
// TODO: We should probably provide options here eventually, but for now
|
||||||
|
// just never require HTTPS for external-domain blogs.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPriority() {
|
||||||
|
return 4000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newSiteForRequest(AphrontRequest $request) {
|
||||||
|
if (!$this->isPhameActive()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$host = $request->getHost();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$blog = id(new PhameBlogQuery())
|
||||||
|
->setViewer(new PhabricatorUser())
|
||||||
|
->withDomain($host)
|
||||||
|
->executeOne();
|
||||||
|
} catch (PhabricatorPolicyException $ex) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'This blog is not visible to logged out users, so it can not be '.
|
||||||
|
'visited from a custom domain.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$blog) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return id(new PhameBlogSite())->setBlog($blog);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPathForRouting(AphrontRequest $request) {
|
||||||
|
$path = $request->getPath();
|
||||||
|
$id = $this->getBlog()->getID();
|
||||||
|
|
||||||
|
return "/phame/live/{$id}/{$path}";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
22
src/applications/phame/site/PhameSite.php
Normal file
22
src/applications/phame/site/PhameSite.php
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class PhameSite extends PhabricatorSite {
|
||||||
|
|
||||||
|
protected function isPhameActive() {
|
||||||
|
$base_uri = PhabricatorEnv::getEnvConfig('phabricator.base-uri');
|
||||||
|
if (!strlen($base_uri)) {
|
||||||
|
// Don't activate Phame if we don't have a base URI configured.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$phame_installed = PhabricatorApplication::isClassInstalled(
|
||||||
|
'PhabricatorPhameApplication');
|
||||||
|
if (!$phame_installed) {
|
||||||
|
// Don't activate Phame if the the application is uninstalled.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue