1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-30 17:30:59 +01:00

Phame - allow blogs to specify custom URIs

Summary: this then enables people to create blog.theircompany.com. And for us, blog.phacility.com...!

Test Plan:
 - created custom URIs of various goodness and verified the error messages were sensical.
 - verified if "false" in configuration then custom uri stuff disappears

Reviewers: epriestley

Reviewed By: epriestley

CC: aran, Korvin

Maniphest Tasks: T1373

Differential Revision: https://secure.phabricator.com/D3542
This commit is contained in:
Bob Trahan 2012-09-30 17:10:27 -07:00
parent f29804a62a
commit 9e1b643896
8 changed files with 147 additions and 26 deletions

View file

@ -735,15 +735,6 @@ return array(
// The Phabricator "Client Secret" to use for Phabricator API access.
'phabricator.application-secret' => null,
// -- Disqus Comments ------------------------------------------------------- //
// Should Phame users have Disqus comment widget, and if so what's the
// website shortname to use? For example, secure.phabricator.org uses
// "phabricator", which we registered with Disqus. If you aren't familiar
// with Disqus, see:
// Disqus quick start guide - http://docs.disqus.com/help/4/
// Information on shortnames - http://docs.disqus.com/help/68/
'disqus.shortname' => null,
// -- Recaptcha ------------------------------------------------------------- //
@ -1070,6 +1061,16 @@ return array(
'phriction.enabled' => true,
// -- Phame ----------------------------------------------------------------- //
// Should Phame users have Disqus comment widget, and if so what's the
// website shortname to use? For example, secure.phabricator.org uses
// "phabricator", which we registered with Disqus. If you aren't familiar
// with Disqus, see:
// Disqus quick start guide - http://docs.disqus.com/help/4/
// Information on shortnames - http://docs.disqus.com/help/68/
'disqus.shortname' => null,
// -- Remarkup -------------------------------------------------------------- //
// If you enable this, linked YouTube videos will be embeded inline. This has

View file

@ -0,0 +1,4 @@
ALTER TABLE `{$NAMESPACE}_phame`.`phame_blog`
ADD COLUMN `domain` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin
AFTER `description`,
ADD UNIQUE KEY (`domain`);

View file

@ -91,9 +91,11 @@ abstract class AphrontApplicationConfiguration {
/**
* Using builtin and application routes, build the appropriate
* @{class:AphrontController} class for the request. To route a request, we
* test the URI against all builtin routes from @{method:getURIMap}, then
* against all application routes from installed
* @{class:PhabricatorApplication}s.
* first test if the HTTP_HOST is configured as a valid Phabricator URI. If
* it isn't, we do a special check to see if it's a custom domain for a blog
* in the Phame application and if that fails we error. Otherwise, we test
* the URI against all builtin routes from @{method:getURIMap}, then against
* all application routes from installed @{class:PhabricatorApplication}s.
*
* If we match a route, we construct the controller it points at, build it,
* and return it.
@ -117,7 +119,6 @@ abstract class AphrontApplicationConfiguration {
*/
final public function buildController() {
$request = $this->getRequest();
$path = $request->getPath();
if (PhabricatorEnv::getEnvConfig('security.require-https')) {
if (!$request->isHTTPS()) {
@ -128,6 +129,41 @@ abstract class AphrontApplicationConfiguration {
}
}
$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');
if ($host != id(new PhutilURI($base_uri))->getDomain() &&
$host != id(new PhutilURI($prod_uri))->getDomain() &&
$host != id(new PhutilURI($file_uri))->getDomain()) {
$blogs = id(new PhameBlogQuery())->withDomain($host)->execute();
$blog = reset($blogs);
if (!$blog) {
if ($prod_uri) {
$prod_str = ' or '.$prod_uri;
} else {
$prod_str = '';
}
throw new Exception(
'Specified domain '.$host.' is not configured for Phabricator '.
'requests. Please use '.$base_uri.$prod_str.' to visit this instance.'
);
}
// 2 basic cases
// -- looking at a list of blog posts, path is nothing or '/'
// -- looking at an actual blog post, path is like /btrahan/post_title
if (!$path || $path == '/') {
$path = $blog->getViewURI();
} else {
$path = '/phame/posts/'.trim($path, '/').'/';
}
// TODO - now we need to tell Celerity to render static resources with
// full URIs like secure.phabricator.org/rsrc/blahblah
}
list($controller, $uri_data) = $this->buildControllerForPath($path);
if (!$controller) {
if (!preg_match('@/$@', $path)) {

View file

@ -78,6 +78,7 @@ final class PhameBlogEditController
$user = $request->getUser();
$e_name = null;
$e_bloggers = null;
$e_custom_domain = null;
$errors = array();
if ($this->isBlogEdit()) {
@ -121,6 +122,7 @@ final class PhameBlogEditController
$name = $request->getStr('name');
$description = $request->getStr('description');
$blogger_arr = $request->getArr('bloggers');
$custom_domain = $request->getStr('custom_domain');
if (empty($blogger_arr)) {
$error = 'Bloggers must be nonempty.';
@ -145,6 +147,14 @@ final class PhameBlogEditController
}
$blog->setName($name);
$blog->setDescription($description);
if (!empty($custom_domain)) {
$error = $blog->validateCustomDomain($custom_domain);
if ($error) {
$errors[] = $error;
$e_custom_domain = 'Invalid';
}
$blog->setDomain($custom_domain);
}
if (empty($errors)) {
$blog->save();
@ -168,7 +178,11 @@ final class PhameBlogEditController
if ($saved) {
$uri = new PhutilURI($blog->getViewURI());
if ($this->isBlogEdit()) {
$uri->setQueryParam('edit', true);
} else {
$uri->setQueryParam('new', true);
}
return id(new AphrontRedirectResponse())
->setURI($uri);
}
@ -208,6 +222,15 @@ final class PhameBlogEditController
->setDatasource('/typeahead/common/users/')
->setError($e_bloggers)
)
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Custom Domain')
->setName('custom_domain')
->setValue($blog->getDomain())
->setCaption('Must include at least one dot (.), e.g. '.
'blog.example.com')
->setError($e_custom_domain)
)
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton('/phame/blog/')

View file

@ -111,6 +111,10 @@ final class PhameBlogViewController
$notice = $this->buildNoticeView()
->setTitle('Successfully created your blog.')
->appendChild('Time to write some posts.');
} else if ($request->getExists('edit')) {
$notice = $this->buildNoticeView()
->setTitle('Successfully edited your blog.')
->appendChild('Time to write some posts.');
} else {
$notice = null;
}

View file

@ -22,6 +22,7 @@
final class PhameBlogQuery extends PhabricatorOffsetPagedQuery {
private $phids;
private $domain;
private $needBloggers;
public function withPHIDs($phids) {
@ -29,6 +30,11 @@ final class PhameBlogQuery extends PhabricatorOffsetPagedQuery {
return $this;
}
public function withDomain($domain) {
$this->domain = $domain;
return $this;
}
public function needBloggers($need_bloggers) {
$this->needBloggers = $need_bloggers;
return $this;
@ -96,7 +102,16 @@ final class PhameBlogQuery extends PhabricatorOffsetPagedQuery {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
$this->phids
);
}
if ($this->domain) {
$where[] = qsprintf(
$conn_r,
'domain = %s',
$this->domain
);
}
return $this->formatWhereClause($where);

View file

@ -25,6 +25,7 @@ final class PhameBlog extends PhameDAO {
protected $phid;
protected $name;
protected $description;
protected $domain;
protected $configData;
protected $creatorPHID;
@ -45,6 +46,38 @@ final class PhameBlog extends PhameDAO {
PhabricatorPHIDConstants::PHID_TYPE_BLOG);
}
/**
* Makes sure a given custom blog uri is properly configured in DNS
* to point at this Phabricator instance. If there is an error in
* the configuration, return a string describing the error and how
* to fix it. If there is no error, return an empty string.
*
* @return string
*/
public function validateCustomDomain($custom_domain) {
$example_domain = '(e.g. blog.example.com)';
$valid = '';
// note this "uri" should be pretty busted given the desired input
// so just use it to test if there's a protocol specified
$uri = new PhutilURI($custom_domain);
if ($uri->getProtocol()) {
return 'Do not specify a protocol, just the domain. '.$example_domain;
}
if (strpos($custom_domain, '/') !== false) {
return 'Do not specify a path, just the domain. '.$example_domain;
}
if (strpos($custom_domain, '.') === false) {
return 'Custom domain must contain at least one dot (.) because '.
'some browsers fail to set cookies on domains such as '.
'http://example. '.$example_domain;
}
return $valid;
}
public function loadBloggerPHIDs() {
if (!$this->getPHID()) {
return $this;

View file

@ -988,6 +988,11 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
'type' => 'sql',
'name' => $this->getPatchPath('draft-metadata.sql'),
),
'phamedomain.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('phamedomain.sql'),
),
);
}