Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15388269
D13474.id32606.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
21 KB
Referenced Files
None
Subscribers
None
D13474.id32606.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -160,6 +160,7 @@
'AphrontRequestTestCase' => 'aphront/__tests__/AphrontRequestTestCase.php',
'AphrontResponse' => 'aphront/response/AphrontResponse.php',
'AphrontSideNavFilterView' => 'view/layout/AphrontSideNavFilterView.php',
+ 'AphrontSite' => 'aphront/site/AphrontSite.php',
'AphrontStackTraceView' => 'view/widget/AphrontStackTraceView.php',
'AphrontStandaloneHTMLResponse' => 'aphront/response/AphrontStandaloneHTMLResponse.php',
'AphrontTableView' => 'view/control/AphrontTableView.php',
@@ -1656,6 +1657,7 @@
'PhabricatorConfigSchemaQuery' => 'applications/config/schema/PhabricatorConfigSchemaQuery.php',
'PhabricatorConfigSchemaSpec' => 'applications/config/schema/PhabricatorConfigSchemaSpec.php',
'PhabricatorConfigServerSchema' => 'applications/config/schema/PhabricatorConfigServerSchema.php',
+ 'PhabricatorConfigSiteModuleController' => 'applications/config/controller/PhabricatorConfigSiteModuleController.php',
'PhabricatorConfigSiteSource' => 'infrastructure/env/PhabricatorConfigSiteSource.php',
'PhabricatorConfigSource' => 'infrastructure/env/PhabricatorConfigSource.php',
'PhabricatorConfigStackSource' => 'infrastructure/env/PhabricatorConfigStackSource.php',
@@ -2325,6 +2327,7 @@
'PhabricatorPhrequentConfigOptions' => 'applications/phrequent/config/PhabricatorPhrequentConfigOptions.php',
'PhabricatorPhrictionApplication' => 'applications/phriction/application/PhabricatorPhrictionApplication.php',
'PhabricatorPhrictionConfigOptions' => 'applications/phriction/config/PhabricatorPhrictionConfigOptions.php',
+ 'PhabricatorPlatformSite' => 'aphront/site/PhabricatorPlatformSite.php',
'PhabricatorPolicies' => 'applications/policy/constants/PhabricatorPolicies.php',
'PhabricatorPolicy' => 'applications/policy/storage/PhabricatorPolicy.php',
'PhabricatorPolicyApplication' => 'applications/policy/application/PhabricatorPolicyApplication.php',
@@ -2522,6 +2525,7 @@
'PhabricatorRepositoryURITestCase' => 'applications/repository/storage/__tests__/PhabricatorRepositoryURITestCase.php',
'PhabricatorRepositoryVCSPassword' => 'applications/repository/storage/PhabricatorRepositoryVCSPassword.php',
'PhabricatorRepositoryVersion' => 'applications/repository/constants/PhabricatorRepositoryVersion.php',
+ 'PhabricatorResourceSite' => 'aphront/site/PhabricatorResourceSite.php',
'PhabricatorRobotsController' => 'applications/system/controller/PhabricatorRobotsController.php',
'PhabricatorS3FileStorageEngine' => 'applications/files/engine/PhabricatorS3FileStorageEngine.php',
'PhabricatorSMS' => 'infrastructure/sms/storage/PhabricatorSMS.php',
@@ -2611,6 +2615,7 @@
'PhabricatorSetupIssue' => 'applications/config/issue/PhabricatorSetupIssue.php',
'PhabricatorSetupIssueUIExample' => 'applications/uiexample/examples/PhabricatorSetupIssueUIExample.php',
'PhabricatorSetupIssueView' => 'applications/config/view/PhabricatorSetupIssueView.php',
+ 'PhabricatorSite' => 'aphront/site/PhabricatorSite.php',
'PhabricatorSlowvoteApplication' => 'applications/slowvote/application/PhabricatorSlowvoteApplication.php',
'PhabricatorSlowvoteChoice' => 'applications/slowvote/storage/PhabricatorSlowvoteChoice.php',
'PhabricatorSlowvoteCloseController' => 'applications/slowvote/controller/PhabricatorSlowvoteCloseController.php',
@@ -2889,6 +2894,8 @@
'PhameBlogListController' => 'applications/phame/controller/blog/PhameBlogListController.php',
'PhameBlogLiveController' => 'applications/phame/controller/blog/PhameBlogLiveController.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',
'PhameBlogTransaction' => 'applications/phame/storage/PhameBlogTransaction.php',
'PhameBlogViewController' => 'applications/phame/controller/blog/PhameBlogViewController.php',
@@ -2917,6 +2924,7 @@
'PhameQueryPostsConduitAPIMethod' => 'applications/phame/conduit/PhameQueryPostsConduitAPIMethod.php',
'PhameResourceController' => 'applications/phame/controller/PhameResourceController.php',
'PhameSchemaSpec' => 'applications/phame/storage/PhameSchemaSpec.php',
+ 'PhameSite' => 'applications/phame/site/PhameSite.php',
'PhameSkinSpecification' => 'applications/phame/skins/PhameSkinSpecification.php',
'PhluxController' => 'applications/phlux/controller/PhluxController.php',
'PhluxDAO' => 'applications/phlux/storage/PhluxDAO.php',
@@ -3523,6 +3531,7 @@
'AphrontRequestTestCase' => 'PhabricatorTestCase',
'AphrontResponse' => 'Phobject',
'AphrontSideNavFilterView' => 'AphrontView',
+ 'AphrontSite' => 'Phobject',
'AphrontStackTraceView' => 'AphrontView',
'AphrontStandaloneHTMLResponse' => 'AphrontHTMLResponse',
'AphrontTableView' => 'AphrontView',
@@ -5263,6 +5272,7 @@
'PhabricatorConfigSchemaQuery' => 'Phobject',
'PhabricatorConfigSchemaSpec' => 'Phobject',
'PhabricatorConfigServerSchema' => 'PhabricatorConfigStorageSchema',
+ 'PhabricatorConfigSiteModuleController' => 'PhabricatorConfigController',
'PhabricatorConfigSiteSource' => 'PhabricatorConfigProxySource',
'PhabricatorConfigSource' => 'Phobject',
'PhabricatorConfigStackSource' => 'PhabricatorConfigSource',
@@ -6022,6 +6032,7 @@
'PhabricatorPhrequentConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorPhrictionApplication' => 'PhabricatorApplication',
'PhabricatorPhrictionConfigOptions' => 'PhabricatorApplicationConfigOptions',
+ 'PhabricatorPlatformSite' => 'PhabricatorSite',
'PhabricatorPolicies' => 'PhabricatorPolicyConstants',
'PhabricatorPolicy' => array(
'PhabricatorPolicyDAO',
@@ -6290,6 +6301,7 @@
'PhabricatorRepositoryURITestCase' => 'PhabricatorTestCase',
'PhabricatorRepositoryVCSPassword' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryVersion' => 'Phobject',
+ 'PhabricatorResourceSite' => 'AphrontSite',
'PhabricatorRobotsController' => 'PhabricatorController',
'PhabricatorS3FileStorageEngine' => 'PhabricatorFileStorageEngine',
'PhabricatorSMS' => 'PhabricatorSMSDAO',
@@ -6381,6 +6393,7 @@
'PhabricatorSetupIssue' => 'Phobject',
'PhabricatorSetupIssueUIExample' => 'PhabricatorUIExample',
'PhabricatorSetupIssueView' => 'AphrontView',
+ 'PhabricatorSite' => 'AphrontSite',
'PhabricatorSlowvoteApplication' => 'PhabricatorApplication',
'PhabricatorSlowvoteChoice' => 'PhabricatorSlowvoteDAO',
'PhabricatorSlowvoteCloseController' => 'PhabricatorSlowvoteController',
@@ -6705,6 +6718,8 @@
'PhameBlogListController' => 'PhameController',
'PhameBlogLiveController' => 'PhameController',
'PhameBlogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+ 'PhameBlogResourceSite' => 'PhameSite',
+ 'PhameBlogSite' => 'PhameSite',
'PhameBlogSkin' => 'PhabricatorController',
'PhameBlogTransaction' => 'PhabricatorApplicationTransaction',
'PhameBlogViewController' => 'PhameController',
@@ -6739,6 +6754,7 @@
'PhameQueryPostsConduitAPIMethod' => 'PhameConduitAPIMethod',
'PhameResourceController' => 'CelerityResourceController',
'PhameSchemaSpec' => 'PhabricatorConfigSchemaSpec',
+ 'PhameSite' => 'PhabricatorSite',
'PhameSkinSpecification' => 'Phobject',
'PhluxController' => 'PhabricatorController',
'PhluxDAO' => 'PhabricatorLiskDAO',
diff --git a/src/aphront/configuration/AphrontApplicationConfiguration.php b/src/aphront/configuration/AphrontApplicationConfiguration.php
--- a/src/aphront/configuration/AphrontApplicationConfiguration.php
+++ b/src/aphront/configuration/AphrontApplicationConfiguration.php
@@ -350,7 +350,9 @@
}
}
- if (PhabricatorEnv::getEnvConfig('security.require-https')) {
+ $site = $this->buildSiteForRequest($request);
+
+ if ($site->shouldRequireHTTPS()) {
if (!$request->isHTTPS()) {
$https_uri = $request->getRequestURI();
$https_uri->setDomain($request->getHost());
@@ -362,82 +364,9 @@
}
}
- $path = $request->getPath();
- $host = $request->getHost();
- $base_uri = PhabricatorEnv::getEnvConfig('phabricator.base-uri');
- $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;
- }
+ // TODO: Really, the Site should get more control here and be able to
+ // do its own routing logic if it wants, but we don't need that for now.
+ $path = $site->getPathForRouting($request);
list($controller, $uri_data) = $this->buildControllerForPath($path);
if (!$controller) {
@@ -509,4 +438,29 @@
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;
+ }
+
}
diff --git a/src/aphront/site/AphrontSite.php b/src/aphront/site/AphrontSite.php
new file mode 100644
--- /dev/null
+++ b/src/aphront/site/AphrontSite.php
@@ -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();
+ }
+
+}
diff --git a/src/aphront/site/PhabricatorPlatformSite.php b/src/aphront/site/PhabricatorPlatformSite.php
new file mode 100644
--- /dev/null
+++ b/src/aphront/site/PhabricatorPlatformSite.php
@@ -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;
+ }
+
+}
diff --git a/src/aphront/site/PhabricatorResourceSite.php b/src/aphront/site/PhabricatorResourceSite.php
new file mode 100644
--- /dev/null
+++ b/src/aphront/site/PhabricatorResourceSite.php
@@ -0,0 +1,45 @@
+<?php
+
+final class PhabricatorResourceSite extends AphrontSite {
+
+ public function getDescription() {
+ return pht('Serves static resources like images, CSS and JS.');
+ }
+
+ public function getPriority() {
+ return 2000;
+ }
+
+ public function shouldRequireHTTPS() {
+ return PhabricatorEnv::getEnvConfig('security.require-https');
+ }
+
+ 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;
+ }
+
+}
diff --git a/src/aphront/site/PhabricatorSite.php b/src/aphront/site/PhabricatorSite.php
new file mode 100644
--- /dev/null
+++ b/src/aphront/site/PhabricatorSite.php
@@ -0,0 +1,9 @@
+<?php
+
+abstract class PhabricatorSite extends AphrontSite {
+
+ public function shouldRequireHTTPS() {
+ return PhabricatorEnv::getEnvConfig('security.require-https');
+ }
+
+}
diff --git a/src/applications/config/application/PhabricatorConfigApplication.php b/src/applications/config/application/PhabricatorConfigApplication.php
--- a/src/applications/config/application/PhabricatorConfigApplication.php
+++ b/src/applications/config/application/PhabricatorConfigApplication.php
@@ -56,6 +56,9 @@
'(?P<key>[^/]+)/' => 'PhabricatorConfigIssueViewController',
),
'cache/' => 'PhabricatorConfigCacheController',
+ 'module/' => array(
+ 'sites/' => 'PhabricatorConfigSiteModuleController',
+ ),
),
);
}
diff --git a/src/applications/config/controller/PhabricatorConfigController.php b/src/applications/config/controller/PhabricatorConfigController.php
--- a/src/applications/config/controller/PhabricatorConfigController.php
+++ b/src/applications/config/controller/PhabricatorConfigController.php
@@ -24,6 +24,8 @@
$nav->addFilter('cache/', pht('Cache Status'));
$nav->addLabel(pht('Welcome'));
$nav->addFilter('welcome/', pht('Welcome Screen'));
+ $nav->addLabel(pht('Modules'));
+ $nav->addFilter('module/sites/', pht('Sites'));
return $nav;
}
diff --git a/src/applications/config/controller/PhabricatorConfigSiteModuleController.php b/src/applications/config/controller/PhabricatorConfigSiteModuleController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/config/controller/PhabricatorConfigSiteModuleController.php
@@ -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')),
+ ));
+ }
+
+}
diff --git a/src/applications/phame/site/PhameBlogResourceSite.php b/src/applications/phame/site/PhameBlogResourceSite.php
new file mode 100644
--- /dev/null
+++ b/src/applications/phame/site/PhameBlogResourceSite.php
@@ -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();
+ }
+
+}
diff --git a/src/applications/phame/site/PhameBlogSite.php b/src/applications/phame/site/PhameBlogSite.php
new file mode 100644
--- /dev/null
+++ b/src/applications/phame/site/PhameBlogSite.php
@@ -0,0 +1,57 @@
+<?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 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}";
+ }
+
+}
diff --git a/src/applications/phame/site/PhameSite.php b/src/applications/phame/site/PhameSite.php
new file mode 100644
--- /dev/null
+++ b/src/applications/phame/site/PhameSite.php
@@ -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;
+ }
+
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Mar 16, 3:33 AM (2 w, 6 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7705508
Default Alt Text
D13474.id32606.diff (21 KB)
Attached To
Mode
D13474: Modularize Aphront "sites"
Attached
Detach File
Event Timeline
Log In to Comment