mirror of
https://github.com/silverstripe/silverstripe-subsites
synced 2024-10-22 09:05:55 +00:00
ENHANCEMENT Allowing strict subdomain checks on 'www.example.com' vs. 'example.com' via Subsite::$strict_domain_matching (AIR-54)
This commit is contained in:
parent
32d51ed986
commit
2b506b02b1
@ -65,6 +65,13 @@ You can mix the two together, if you want to have some subsites hosted off subdo
|
||||
|
||||
Note that every site also has a ''www.''-prefixed version of the domain available. For example, if your subsite is accessible from ''wellington.example.org'' then it will also be accessible from '''www.wellington.example.org''.
|
||||
|
||||
### Strict Subdomain Matching ###
|
||||
|
||||
The module tries to provide sensible defaults, in which it regards `example.com` and `www.example.com`
|
||||
as the same domains. In case you want to distinguish between these variations,
|
||||
set `Subsite::$strict_subdomain_matching` to TRUE. This won't affect wildcard/asterisk checks,
|
||||
but removes the ambiguity about default subdomains.
|
||||
|
||||
### Permissions ###
|
||||
|
||||
Groups can be associated with one or more subsites, in which case the granted permissions
|
||||
|
@ -20,6 +20,7 @@ class Subsite extends DataObject implements PermissionProvider {
|
||||
static $force_subsite = null;
|
||||
|
||||
static $write_hostmap = true;
|
||||
|
||||
static $default_sort = "\"Title\" ASC";
|
||||
|
||||
static $db = array(
|
||||
@ -76,6 +77,13 @@ class Subsite extends DataObject implements PermissionProvider {
|
||||
* are listed.
|
||||
*/
|
||||
protected static $allowed_themes = array();
|
||||
|
||||
/**
|
||||
* @var Boolean If set to TRUE, don't assume 'www.example.com' and 'example.com' are the same.
|
||||
* Doesn't affect wildcard matching, so '*.example.com' will match 'www.example.com' (but not 'example.com')
|
||||
* in both TRUE or FALSE setting.
|
||||
*/
|
||||
static $strict_subdomain_matching = false;
|
||||
|
||||
static function set_allowed_domains($domain){
|
||||
user_error('Subsite::set_allowed_domains() is deprecated; it is no longer necessary '
|
||||
@ -320,7 +328,7 @@ JS;
|
||||
static function getSubsiteIDForDomain($host = null, $returnMainIfNotFound = true) {
|
||||
if($host == null) $host = $_SERVER['HTTP_HOST'];
|
||||
|
||||
$host = str_replace('www.','',$host);
|
||||
if(!Subsite::$strict_subdomain_matching) $host = preg_replace('/^www\./', '', $host);
|
||||
$SQL_host = Convert::raw2sql($host);
|
||||
|
||||
$matchingDomains = DataObject::get("SubsiteDomain", "'$SQL_host' LIKE replace(\"SubsiteDomain\".\"Domain\",'*','%')",
|
||||
@ -329,7 +337,15 @@ JS;
|
||||
|
||||
if($matchingDomains) {
|
||||
$subsiteIDs = array_unique($matchingDomains->column('SubsiteID'));
|
||||
if(sizeof($subsiteIDs) > 1) user_error("Multiple subsites match '$host'", E_USER_WARNING);
|
||||
$subsiteDomains = array_unique($matchingDomains->column('Domain'));
|
||||
if(sizeof($subsiteIDs) > 1) {
|
||||
throw new UnexpectedValueException(sprintf(
|
||||
"Multiple subsites match on '%s': %s",
|
||||
$host,
|
||||
implode(',', $subsiteDomains)
|
||||
));
|
||||
}
|
||||
|
||||
return $subsiteIDs[0];
|
||||
}
|
||||
|
||||
@ -538,7 +554,9 @@ JS;
|
||||
if ($subsites) foreach($subsites as $subsite) {
|
||||
$domains = $subsite->Domains();
|
||||
if ($domains) foreach($domains as $domain) {
|
||||
$hostmap[str_replace('www.', '', $domain->Domain)] = $subsite->domain();
|
||||
$domainStr = $domain->Domain;
|
||||
if(!Subsite::$strict_subdomain_matching) $domainStr = preg_replace('/^www\./', '', $domainStr);
|
||||
$hostmap[$domainStr] = $subsite->domain();
|
||||
}
|
||||
if ($subsite->DefaultSite) $hostmap['default'] = $subsite->domain();
|
||||
}
|
||||
|
@ -1,7 +1,21 @@
|
||||
<?php
|
||||
|
||||
class SubsiteTest extends SapphireTest {
|
||||
|
||||
static $fixture_file = 'subsites/tests/SubsiteTest.yml';
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->origStrictSubdomainMatching = Subsite::$strict_subdomain_matching;
|
||||
Subsite::$strict_subdomain_matching = false;
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
parent::tearDown();
|
||||
|
||||
Subsite::$strict_subdomain_matching = $this->origStrictSubdomainMatching;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new subsite from the template and verify that all the template's pages are copied
|
||||
@ -57,28 +71,65 @@ class SubsiteTest extends SapphireTest {
|
||||
* Confirm that domain lookup is working
|
||||
*/
|
||||
function testDomainLookup() {
|
||||
// Clear existing fixtures
|
||||
foreach(DataObject::get('Subsite') as $subsite) $subsite->delete();
|
||||
foreach(DataObject::get('SubsiteDomain') as $domain) $domain->delete();
|
||||
|
||||
// Much more expressive than YML in this case
|
||||
$subsite1 = $this->createSubsiteWithDomains(array(
|
||||
'one.example.org' => true,
|
||||
'one.*' => false,
|
||||
));
|
||||
$subsite2 = $this->createSubsiteWithDomains(array(
|
||||
'two.mysite.com' => true,
|
||||
'*.mysite.com' => false,
|
||||
'subdomain.onmultiplesubsites.com' => false,
|
||||
));
|
||||
$subsite3 = $this->createSubsiteWithDomains(array(
|
||||
'three.*' => true, // wildcards in primary domain are not recommended
|
||||
'subdomain.unique.com' => false,
|
||||
'*.onmultiplesubsites.com' => false,
|
||||
));
|
||||
|
||||
$this->assertEquals(
|
||||
$this->idFromFixture('Subsite','domaintest1'),
|
||||
$subsite3->ID,
|
||||
Subsite::getSubsiteIDForDomain('subdomain.unique.com'),
|
||||
'Full unique match'
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
$subsite1->ID,
|
||||
Subsite::getSubsiteIDForDomain('one.example.org'),
|
||||
'Full match'
|
||||
'Full match, doesn\'t complain about multiple matches within a single subsite'
|
||||
);
|
||||
|
||||
$failed = false;
|
||||
try {
|
||||
Subsite::getSubsiteIDForDomain('subdomain.onmultiplesubsites.com');
|
||||
} catch(UnexpectedValueException $e) {
|
||||
$failed = true;
|
||||
}
|
||||
$this->assertTrue(
|
||||
$failed,
|
||||
'Fails on multiple matches with wildcard vs. www across multiple subsites'
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
$this->idFromFixture('Subsite','domaintest1'),
|
||||
Subsite::getSubsiteIDForDomain('one.localhost'),
|
||||
'Fuzzy match suffixed with asterisk (rule "one.*")'
|
||||
$subsite1->ID,
|
||||
Subsite::getSubsiteIDForDomain('one.unique.com'),
|
||||
'Fuzzy match suffixed with wildcard (rule "one.*")'
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
$this->idFromFixture('Subsite','domaintest2'),
|
||||
$subsite2->ID,
|
||||
Subsite::getSubsiteIDForDomain('two.mysite.com'),
|
||||
'Matches correct subsite for rule'
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
$this->idFromFixture('Subsite','domaintest2'),
|
||||
$subsite2->ID,
|
||||
Subsite::getSubsiteIDForDomain('other.mysite.com'),
|
||||
'Fuzzy match prefixed with asterisk (rule "*.mysite.com")'
|
||||
'Fuzzy match prefixed with wildcard (rule "*.mysite.com")'
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
@ -88,6 +139,90 @@ class SubsiteTest extends SapphireTest {
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
function testStrictSubdomainMatching() {
|
||||
// Clear existing fixtures
|
||||
foreach(DataObject::get('Subsite') as $subsite) $subsite->delete();
|
||||
foreach(DataObject::get('SubsiteDomain') as $domain) $domain->delete();
|
||||
|
||||
// Much more expressive than YML in this case
|
||||
$subsite1 = $this->createSubsiteWithDomains(array(
|
||||
'example.org' => true,
|
||||
'example.com' => false,
|
||||
'*.wildcard.com' => false,
|
||||
));
|
||||
$subsite2 = $this->createSubsiteWithDomains(array(
|
||||
'www.example.org' => true,
|
||||
'www.wildcard.com' => false,
|
||||
));
|
||||
|
||||
Subsite::$strict_subdomain_matching = false;
|
||||
|
||||
$this->assertEquals(
|
||||
$subsite1->ID,
|
||||
Subsite::getSubsiteIDForDomain('example.org'),
|
||||
'Exact matches without strict checking when not using www prefix'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$subsite1->ID,
|
||||
Subsite::getSubsiteIDForDomain('www.example.org'),
|
||||
'Matches without strict checking when using www prefix, still matching first domain regardless of www prefix (falling back to subsite primary key ordering)'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$subsite1->ID,
|
||||
Subsite::getSubsiteIDForDomain('www.example.com'),
|
||||
'Fuzzy matches without strict checking with www prefix'
|
||||
);
|
||||
$this->assertEquals(
|
||||
0,
|
||||
Subsite::getSubsiteIDForDomain('www.wildcard.com'),
|
||||
'Doesn\'t match www prefix without strict check, even if a wildcard subdomain is in place'
|
||||
);
|
||||
|
||||
Subsite::$strict_subdomain_matching = true;
|
||||
|
||||
$this->assertEquals(
|
||||
$subsite1->ID,
|
||||
Subsite::getSubsiteIDForDomain('example.org'),
|
||||
'Matches with strict checking when not using www prefix'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$subsite2->ID, // not 1
|
||||
Subsite::getSubsiteIDForDomain('www.example.org'),
|
||||
'Matches with strict checking when using www prefix'
|
||||
);
|
||||
$this->assertEquals(
|
||||
0,
|
||||
Subsite::getSubsiteIDForDomain('www.example.com'),
|
||||
'Doesn\'t fuzzy match with strict checking when using www prefix'
|
||||
);
|
||||
$failed = false;
|
||||
try {
|
||||
Subsite::getSubsiteIDForDomain('www.wildcard.com');
|
||||
} catch(UnexpectedValueException $e) {
|
||||
$failed = true;
|
||||
}
|
||||
$this->assertTrue(
|
||||
$failed,
|
||||
'Fails on multiple matches with strict checking and wildcard vs. www'
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
protected function createSubsiteWithDomains($domains) {
|
||||
$subsite = new Subsite();
|
||||
$subsite->write();
|
||||
foreach($domains as $domainStr => $isPrimary) {
|
||||
$domain = new SubsiteDomain(array(
|
||||
'Domain' => $domainStr,
|
||||
'IsPrimary' => $isPrimary,
|
||||
'SubsiteID' => $subsite->ID
|
||||
));
|
||||
$domain->write();
|
||||
}
|
||||
|
||||
return $subsite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the Subsite->domain() method
|
||||
|
Loading…
x
Reference in New Issue
Block a user