mirror of
https://github.com/silverstripe/silverstripe-subsites
synced 2024-06-14 16:51:38 +02: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''.
|
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 ###
|
### Permissions ###
|
||||||
|
|
||||||
Groups can be associated with one or more subsites, in which case the granted 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 $force_subsite = null;
|
||||||
|
|
||||||
static $write_hostmap = true;
|
static $write_hostmap = true;
|
||||||
|
|
||||||
static $default_sort = "\"Title\" ASC";
|
static $default_sort = "\"Title\" ASC";
|
||||||
|
|
||||||
static $db = array(
|
static $db = array(
|
||||||
|
@ -76,6 +77,13 @@ class Subsite extends DataObject implements PermissionProvider {
|
||||||
* are listed.
|
* are listed.
|
||||||
*/
|
*/
|
||||||
protected static $allowed_themes = array();
|
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){
|
static function set_allowed_domains($domain){
|
||||||
user_error('Subsite::set_allowed_domains() is deprecated; it is no longer necessary '
|
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) {
|
static function getSubsiteIDForDomain($host = null, $returnMainIfNotFound = true) {
|
||||||
if($host == null) $host = $_SERVER['HTTP_HOST'];
|
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);
|
$SQL_host = Convert::raw2sql($host);
|
||||||
|
|
||||||
$matchingDomains = DataObject::get("SubsiteDomain", "'$SQL_host' LIKE replace(\"SubsiteDomain\".\"Domain\",'*','%')",
|
$matchingDomains = DataObject::get("SubsiteDomain", "'$SQL_host' LIKE replace(\"SubsiteDomain\".\"Domain\",'*','%')",
|
||||||
|
@ -329,7 +337,15 @@ JS;
|
||||||
|
|
||||||
if($matchingDomains) {
|
if($matchingDomains) {
|
||||||
$subsiteIDs = array_unique($matchingDomains->column('SubsiteID'));
|
$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];
|
return $subsiteIDs[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,7 +554,9 @@ JS;
|
||||||
if ($subsites) foreach($subsites as $subsite) {
|
if ($subsites) foreach($subsites as $subsite) {
|
||||||
$domains = $subsite->Domains();
|
$domains = $subsite->Domains();
|
||||||
if ($domains) foreach($domains as $domain) {
|
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();
|
if ($subsite->DefaultSite) $hostmap['default'] = $subsite->domain();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,21 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
class SubsiteTest extends SapphireTest {
|
class SubsiteTest extends SapphireTest {
|
||||||
|
|
||||||
static $fixture_file = 'subsites/tests/SubsiteTest.yml';
|
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
|
* 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
|
* Confirm that domain lookup is working
|
||||||
*/
|
*/
|
||||||
function testDomainLookup() {
|
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->assertEquals(
|
||||||
$this->idFromFixture('Subsite','domaintest1'),
|
$subsite3->ID,
|
||||||
|
Subsite::getSubsiteIDForDomain('subdomain.unique.com'),
|
||||||
|
'Full unique match'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
$subsite1->ID,
|
||||||
Subsite::getSubsiteIDForDomain('one.example.org'),
|
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->assertEquals(
|
||||||
$this->idFromFixture('Subsite','domaintest1'),
|
$subsite1->ID,
|
||||||
Subsite::getSubsiteIDForDomain('one.localhost'),
|
Subsite::getSubsiteIDForDomain('one.unique.com'),
|
||||||
'Fuzzy match suffixed with asterisk (rule "one.*")'
|
'Fuzzy match suffixed with wildcard (rule "one.*")'
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
$this->idFromFixture('Subsite','domaintest2'),
|
$subsite2->ID,
|
||||||
Subsite::getSubsiteIDForDomain('two.mysite.com'),
|
Subsite::getSubsiteIDForDomain('two.mysite.com'),
|
||||||
'Matches correct subsite for rule'
|
'Matches correct subsite for rule'
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
$this->idFromFixture('Subsite','domaintest2'),
|
$subsite2->ID,
|
||||||
Subsite::getSubsiteIDForDomain('other.mysite.com'),
|
Subsite::getSubsiteIDForDomain('other.mysite.com'),
|
||||||
'Fuzzy match prefixed with asterisk (rule "*.mysite.com")'
|
'Fuzzy match prefixed with wildcard (rule "*.mysite.com")'
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertEquals(
|
$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
|
* Test the Subsite->domain() method
|
||||||
|
|
Loading…
Reference in New Issue
Block a user