2008-04-26 08:31:52 +02:00
|
|
|
<?php
|
2008-06-15 15:33:53 +02:00
|
|
|
/**
|
2012-04-12 08:02:46 +02:00
|
|
|
* @package framework
|
2008-06-15 15:33:53 +02:00
|
|
|
* @subpackage tests
|
|
|
|
*/
|
2009-12-16 06:39:39 +01:00
|
|
|
class MemberTest extends FunctionalTest {
|
2011-03-30 08:49:11 +02:00
|
|
|
static $fixture_file = 'MemberTest.yml';
|
2008-04-26 08:31:52 +02:00
|
|
|
|
2010-03-09 05:10:38 +01:00
|
|
|
protected $orig = array();
|
2010-10-19 00:33:41 +02:00
|
|
|
protected $local = null;
|
2010-10-19 05:01:29 +02:00
|
|
|
|
|
|
|
protected $illegalExtensions = array(
|
|
|
|
'Member' => array(
|
|
|
|
// TODO Coupling with modules, this should be resolved by automatically
|
|
|
|
// removing all applied extensions before a unit test
|
|
|
|
'ForumRole',
|
|
|
|
'OpenIDAuthenticatedRole'
|
|
|
|
)
|
|
|
|
);
|
2010-10-19 00:33:41 +02:00
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function __construct() {
|
2010-10-19 00:33:41 +02:00
|
|
|
parent::__construct();
|
|
|
|
|
|
|
|
//Setting the locale has to happen in the constructor (using the setUp and tearDown methods doesn't work)
|
|
|
|
//This is because the test relies on the yaml file being interpreted according to a particular date format
|
|
|
|
//and this setup occurs before the setUp method is run
|
|
|
|
$this->local = i18n::default_locale();
|
|
|
|
i18n::set_default_locale('en_US');
|
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function __destruct() {
|
2012-12-08 12:20:20 +01:00
|
|
|
i18n::set_default_locale($this->local);
|
|
|
|
}
|
2010-10-19 00:33:41 +02:00
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function setUp() {
|
2009-11-06 03:23:21 +01:00
|
|
|
parent::setUp();
|
|
|
|
|
2010-03-09 05:10:38 +01:00
|
|
|
$this->orig['Member_unique_identifier_field'] = Member::get_unique_identifier_field();
|
|
|
|
Member::set_unique_identifier_field('Email');
|
2009-11-06 03:23:21 +01:00
|
|
|
Member::set_password_validator(null);
|
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function tearDown() {
|
2010-03-09 05:10:38 +01:00
|
|
|
Member::set_unique_identifier_field($this->orig['Member_unique_identifier_field']);
|
2010-10-19 00:33:41 +02:00
|
|
|
|
2010-03-09 05:10:38 +01:00
|
|
|
parent::tearDown();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @expectedException ValidationException
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testWriteDoesntMergeNewRecordWithExistingMember() {
|
2010-03-09 05:10:38 +01:00
|
|
|
$m1 = new Member();
|
|
|
|
$m1->Email = 'member@test.com';
|
|
|
|
$m1->write();
|
|
|
|
|
|
|
|
$m2 = new Member();
|
|
|
|
$m2->Email = 'member@test.com';
|
|
|
|
$m2->write();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @expectedException ValidationException
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testWriteDoesntMergeExistingMemberOnIdentifierChange() {
|
2010-03-09 05:10:38 +01:00
|
|
|
$m1 = new Member();
|
|
|
|
$m1->Email = 'member@test.com';
|
|
|
|
$m1->write();
|
|
|
|
|
|
|
|
$m2 = new Member();
|
|
|
|
$m2->Email = 'member_new@test.com';
|
|
|
|
$m2->write();
|
|
|
|
|
|
|
|
$m2->Email = 'member@test.com';
|
|
|
|
$m2->write();
|
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testDefaultPasswordEncryptionOnMember() {
|
2010-10-15 05:52:38 +02:00
|
|
|
$memberWithPassword = new Member();
|
|
|
|
$memberWithPassword->Password = 'mypassword';
|
|
|
|
$memberWithPassword->write();
|
2009-11-06 03:23:21 +01:00
|
|
|
$this->assertEquals(
|
2010-10-15 05:52:38 +02:00
|
|
|
$memberWithPassword->PasswordEncryption,
|
2009-11-06 03:23:21 +01:00
|
|
|
Security::get_password_encryption_algorithm(),
|
2010-10-15 05:52:38 +02:00
|
|
|
'Password encryption is set for new member records on first write (with setting "Password")'
|
|
|
|
);
|
|
|
|
|
|
|
|
$memberNoPassword = new Member();
|
|
|
|
$memberNoPassword->write();
|
|
|
|
$this->assertNull(
|
|
|
|
$memberNoPassword->PasswordEncryption,
|
|
|
|
'Password encryption is not set for new member records on first write, when not setting a "Password")'
|
2009-11-06 03:23:21 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testDefaultPasswordEncryptionDoesntChangeExistingMembers() {
|
2009-11-06 03:23:21 +01:00
|
|
|
$member = new Member();
|
|
|
|
$member->Password = 'mypassword';
|
|
|
|
$member->PasswordEncryption = 'sha1_v2.4';
|
|
|
|
$member->write();
|
|
|
|
|
2010-10-15 05:52:38 +02:00
|
|
|
$origAlgo = Security::get_password_encryption_algorithm();
|
2009-11-06 03:23:21 +01:00
|
|
|
Security::set_password_encryption_algorithm('none');
|
2010-10-15 05:52:38 +02:00
|
|
|
|
2009-11-06 03:23:21 +01:00
|
|
|
$member->Password = 'mynewpassword';
|
|
|
|
$member->write();
|
|
|
|
|
|
|
|
$this->assertEquals(
|
|
|
|
$member->PasswordEncryption,
|
|
|
|
'sha1_v2.4'
|
|
|
|
);
|
2010-02-23 05:05:34 +01:00
|
|
|
$result = $member->checkPassword('mynewpassword');
|
|
|
|
$this->assertTrue($result->valid());
|
2010-10-15 05:52:38 +02:00
|
|
|
|
|
|
|
Security::set_password_encryption_algorithm($origAlgo);
|
2009-11-06 03:23:21 +01:00
|
|
|
}
|
2013-01-06 21:20:02 +01:00
|
|
|
|
|
|
|
public function testKeepsEncryptionOnEmptyPasswords() {
|
|
|
|
$member = new Member();
|
|
|
|
$member->Password = 'mypassword';
|
|
|
|
$member->PasswordEncryption = 'sha1_v2.4';
|
|
|
|
$member->write();
|
|
|
|
|
|
|
|
$member->Password = '';
|
|
|
|
$member->write();
|
|
|
|
|
|
|
|
$this->assertEquals(
|
|
|
|
$member->PasswordEncryption,
|
|
|
|
'sha1_v2.4'
|
|
|
|
);
|
|
|
|
$result = $member->checkPassword('');
|
|
|
|
$this->assertTrue($result->valid());
|
|
|
|
}
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testSetPassword() {
|
2009-11-06 03:23:21 +01:00
|
|
|
$member = $this->objFromFixture('Member', 'test');
|
|
|
|
$member->Password = "test1";
|
|
|
|
$member->write();
|
2010-02-23 05:05:34 +01:00
|
|
|
$result = $member->checkPassword('test1');
|
|
|
|
$this->assertTrue($result->valid());
|
2009-11-06 03:23:21 +01:00
|
|
|
}
|
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
/**
|
|
|
|
* Test that password changes are logged properly
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testPasswordChangeLogging() {
|
2008-04-26 08:31:52 +02:00
|
|
|
$member = $this->objFromFixture('Member', 'test');
|
2008-08-11 07:17:37 +02:00
|
|
|
$this->assertNotNull($member);
|
2008-04-26 08:31:52 +02:00
|
|
|
$member->Password = "test1";
|
|
|
|
$member->write();
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
$member->Password = "test2";
|
|
|
|
$member->write();
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
$member->Password = "test3";
|
|
|
|
$member->write();
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2012-09-26 23:34:00 +02:00
|
|
|
$passwords = DataObject::get("MemberPassword", "\"MemberID\" = $member->ID", "\"Created\" DESC, \"ID\" DESC")
|
|
|
|
->getIterator();
|
2008-04-26 08:31:52 +02:00
|
|
|
$this->assertNotNull($passwords);
|
2011-05-03 04:16:40 +02:00
|
|
|
$passwords->rewind();
|
|
|
|
$this->assertTrue($passwords->current()->checkPassword('test3'), "Password test3 not found in MemberRecord");
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2011-05-03 04:16:40 +02:00
|
|
|
$passwords->next();
|
|
|
|
$this->assertTrue($passwords->current()->checkPassword('test2'), "Password test2 not found in MemberRecord");
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2011-05-03 04:16:40 +02:00
|
|
|
$passwords->next();
|
|
|
|
$this->assertTrue($passwords->current()->checkPassword('test1'), "Password test1 not found in MemberRecord");
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2011-05-03 04:16:40 +02:00
|
|
|
$passwords->next();
|
2012-05-09 12:43:22 +02:00
|
|
|
$this->assertInstanceOf('DataObject', $passwords->current());
|
2012-09-26 23:34:00 +02:00
|
|
|
$this->assertTrue($passwords->current()->checkPassword('1nitialPassword'),
|
|
|
|
"Password 1nitialPassword not found in MemberRecord");
|
2008-04-26 08:31:52 +02:00
|
|
|
}
|
|
|
|
|
2008-04-26 08:32:42 +02:00
|
|
|
/**
|
|
|
|
* Test that changed passwords will send an email
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testChangedPasswordEmaling() {
|
2008-04-26 08:32:42 +02:00
|
|
|
$this->clearEmails();
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:32:42 +02:00
|
|
|
$member = $this->objFromFixture('Member', 'test');
|
2008-08-11 07:17:37 +02:00
|
|
|
$this->assertNotNull($member);
|
2008-04-26 08:32:42 +02:00
|
|
|
$valid = $member->changePassword('32asDF##$$%%');
|
|
|
|
$this->assertTrue($valid->valid());
|
2008-05-15 10:46:12 +02:00
|
|
|
/*
|
2012-09-26 23:34:00 +02:00
|
|
|
$this->assertEmailSent("sam@silverstripe.com", null, "/changed password/",
|
|
|
|
'/sam@silverstripe\.com.*32asDF##\$\$%%/');
|
2008-05-15 10:46:12 +02:00
|
|
|
*/
|
2008-04-26 08:32:42 +02:00
|
|
|
}
|
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
/**
|
|
|
|
* Test that passwords validate against NZ e-government guidelines
|
|
|
|
* - don't allow the use of the last 6 passwords
|
|
|
|
* - require at least 3 of lowercase, uppercase, digits and punctuation
|
|
|
|
* - at least 7 characters long
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testValidatePassword() {
|
2008-04-26 08:31:52 +02:00
|
|
|
$member = $this->objFromFixture('Member', 'test');
|
2008-08-11 07:17:37 +02:00
|
|
|
$this->assertNotNull($member);
|
2008-04-26 08:31:52 +02:00
|
|
|
|
2012-03-02 00:28:04 +01:00
|
|
|
Member::set_password_validator(new MemberTest_PasswordValidator());
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
// BAD PASSWORDS
|
|
|
|
|
|
|
|
$valid = $member->changePassword('shorty');
|
|
|
|
$this->assertFalse($valid->valid());
|
|
|
|
$this->assertContains("TOO_SHORT", $valid->codeList());
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
$valid = $member->changePassword('longone');
|
|
|
|
$this->assertNotContains("TOO_SHORT", $valid->codeList());
|
|
|
|
$this->assertContains("LOW_CHARACTER_STRENGTH", $valid->codeList());
|
|
|
|
$this->assertFalse($valid->valid());
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
$valid = $member->changePassword('w1thNumb3rs');
|
|
|
|
$this->assertNotContains("LOW_CHARACTER_STRENGTH", $valid->codeList());
|
|
|
|
$this->assertTrue($valid->valid());
|
|
|
|
|
|
|
|
// Clear out the MemberPassword table to ensure that the system functions properly in that situation
|
2008-11-24 10:31:14 +01:00
|
|
|
DB::query("DELETE FROM \"MemberPassword\"");
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
// GOOD PASSWORDS
|
|
|
|
|
|
|
|
$valid = $member->changePassword('withSym###Ls');
|
|
|
|
$this->assertNotContains("LOW_CHARACTER_STRENGTH", $valid->codeList());
|
|
|
|
$this->assertTrue($valid->valid());
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
$valid = $member->changePassword('withSym###Ls2');
|
|
|
|
$this->assertTrue($valid->valid());
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
$valid = $member->changePassword('withSym###Ls3');
|
|
|
|
$this->assertTrue($valid->valid());
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
$valid = $member->changePassword('withSym###Ls4');
|
|
|
|
$this->assertTrue($valid->valid());
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
$valid = $member->changePassword('withSym###Ls5');
|
|
|
|
$this->assertTrue($valid->valid());
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
$valid = $member->changePassword('withSym###Ls6');
|
|
|
|
$this->assertTrue($valid->valid());
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
$valid = $member->changePassword('withSym###Ls7');
|
|
|
|
$this->assertTrue($valid->valid());
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
// CAN'T USE PASSWORDS 2-7, but I can use pasword 1
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
$valid = $member->changePassword('withSym###Ls2');
|
|
|
|
$this->assertFalse($valid->valid());
|
|
|
|
$this->assertContains("PREVIOUS_PASSWORD", $valid->codeList());
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
$valid = $member->changePassword('withSym###Ls5');
|
|
|
|
$this->assertFalse($valid->valid());
|
|
|
|
$this->assertContains("PREVIOUS_PASSWORD", $valid->codeList());
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
$valid = $member->changePassword('withSym###Ls7');
|
|
|
|
$this->assertFalse($valid->valid());
|
|
|
|
$this->assertContains("PREVIOUS_PASSWORD", $valid->codeList());
|
|
|
|
|
|
|
|
$valid = $member->changePassword('withSym###Ls');
|
|
|
|
$this->assertTrue($valid->valid());
|
|
|
|
|
|
|
|
// HAVING DONE THAT, PASSWORD 2 is now available from the list
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
$valid = $member->changePassword('withSym###Ls2');
|
|
|
|
$this->assertTrue($valid->valid());
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
$valid = $member->changePassword('withSym###Ls3');
|
|
|
|
$this->assertTrue($valid->valid());
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
$valid = $member->changePassword('withSym###Ls4');
|
|
|
|
$this->assertTrue($valid->valid());
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-05-15 10:46:12 +02:00
|
|
|
Member::set_password_validator(null);
|
2008-04-26 08:31:52 +02:00
|
|
|
}
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
/**
|
|
|
|
* Test that the PasswordExpiry date is set when passwords are changed
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testPasswordExpirySetting() {
|
2008-04-26 08:31:52 +02:00
|
|
|
Member::set_password_expiry(90);
|
|
|
|
|
|
|
|
$member = $this->objFromFixture('Member', 'test');
|
2008-08-11 07:17:37 +02:00
|
|
|
$this->assertNotNull($member);
|
2008-04-26 08:31:52 +02:00
|
|
|
$valid = $member->changePassword("Xx?1234234");
|
|
|
|
$this->assertTrue($valid->valid());
|
|
|
|
|
|
|
|
$expiryDate = date('Y-m-d', time() + 90*86400);
|
|
|
|
$this->assertEquals($expiryDate, $member->PasswordExpiry);
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
Member::set_password_expiry(null);
|
|
|
|
$valid = $member->changePassword("Xx?1234235");
|
|
|
|
$this->assertTrue($valid->valid());
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
$this->assertNull($member->PasswordExpiry);
|
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testIsPasswordExpired() {
|
2008-04-26 08:31:52 +02:00
|
|
|
$member = $this->objFromFixture('Member', 'test');
|
2008-08-11 07:17:37 +02:00
|
|
|
$this->assertNotNull($member);
|
2008-04-26 08:31:52 +02:00
|
|
|
$this->assertFalse($member->isPasswordExpired());
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
$member = $this->objFromFixture('Member', 'noexpiry');
|
|
|
|
$member->PasswordExpiry = null;
|
|
|
|
$this->assertFalse($member->isPasswordExpired());
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
$member = $this->objFromFixture('Member', 'expiredpassword');
|
|
|
|
$this->assertTrue($member->isPasswordExpired());
|
|
|
|
|
|
|
|
// Check the boundary conditions
|
|
|
|
// If PasswordExpiry == today, then it's expired
|
|
|
|
$member->PasswordExpiry = date('Y-m-d');
|
|
|
|
$this->assertTrue($member->isPasswordExpired());
|
2009-11-06 03:23:21 +01:00
|
|
|
|
2008-04-26 08:31:52 +02:00
|
|
|
// If PasswordExpiry == tomorrow, then it's not
|
|
|
|
$member->PasswordExpiry = date('Y-m-d', time() + 86400);
|
|
|
|
$this->assertFalse($member->isPasswordExpired());
|
|
|
|
|
|
|
|
}
|
2010-10-19 04:46:26 +02:00
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testMemberWithNoDateFormatFallsbackToGlobalLocaleDefaultFormat() {
|
2010-10-15 05:23:02 +02:00
|
|
|
$member = $this->objFromFixture('Member', 'noformatmember');
|
2011-05-30 21:55:12 +02:00
|
|
|
$this->assertEquals('MMM d, y', $member->DateFormat);
|
|
|
|
$this->assertEquals('h:mm:ss a', $member->TimeFormat);
|
2010-10-15 05:23:02 +02:00
|
|
|
}
|
2010-10-19 04:46:26 +02:00
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testMemberWithNoDateFormatFallsbackToTheirLocaleDefaultFormat() {
|
2010-10-15 05:23:02 +02:00
|
|
|
$member = $this->objFromFixture('Member', 'delocalemember');
|
|
|
|
$this->assertEquals('dd.MM.yyyy', $member->DateFormat);
|
|
|
|
$this->assertEquals('HH:mm:ss', $member->TimeFormat);
|
|
|
|
}
|
2010-10-19 04:46:26 +02:00
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testInGroups() {
|
2008-11-03 02:57:16 +01:00
|
|
|
$staffmember = $this->objFromFixture('Member', 'staffmember');
|
|
|
|
$managementmember = $this->objFromFixture('Member', 'managementmember');
|
|
|
|
$accountingmember = $this->objFromFixture('Member', 'accountingmember');
|
|
|
|
$ceomember = $this->objFromFixture('Member', 'ceomember');
|
|
|
|
|
|
|
|
$staffgroup = $this->objFromFixture('Group', 'staffgroup');
|
|
|
|
$managementgroup = $this->objFromFixture('Group', 'managementgroup');
|
|
|
|
$accountinggroup = $this->objFromFixture('Group', 'accountinggroup');
|
|
|
|
$ceogroup = $this->objFromFixture('Group', 'ceogroup');
|
|
|
|
|
|
|
|
$this->assertTrue(
|
|
|
|
$staffmember->inGroups(array($staffgroup, $managementgroup)),
|
|
|
|
'inGroups() succeeds if a membership is detected on one of many passed groups'
|
|
|
|
);
|
|
|
|
$this->assertFalse(
|
|
|
|
$staffmember->inGroups(array($ceogroup, $managementgroup)),
|
|
|
|
'inGroups() fails if a membership is detected on none of the passed groups'
|
|
|
|
);
|
|
|
|
$this->assertFalse(
|
|
|
|
$ceomember->inGroups(array($staffgroup, $managementgroup), true),
|
|
|
|
'inGroups() fails if no direct membership is detected on any of the passed groups (in strict mode)'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testAddToGroupByCode() {
|
2010-10-15 05:00:48 +02:00
|
|
|
$grouplessMember = $this->objFromFixture('Member', 'grouplessmember');
|
|
|
|
$memberlessGroup = $this->objFromFixture('Group','memberlessgroup');
|
|
|
|
|
|
|
|
$this->assertFalse($grouplessMember->Groups()->exists());
|
|
|
|
$this->assertFalse($memberlessGroup->Members()->exists());
|
2010-10-19 04:46:26 +02:00
|
|
|
|
2010-10-15 05:00:48 +02:00
|
|
|
$grouplessMember->addToGroupByCode('memberless');
|
2010-10-19 04:46:26 +02:00
|
|
|
|
2010-10-15 05:00:48 +02:00
|
|
|
$this->assertEquals($memberlessGroup->Members()->Count(), 1);
|
|
|
|
$this->assertEquals($grouplessMember->Groups()->Count(), 1);
|
|
|
|
|
|
|
|
$grouplessMember->addToGroupByCode('somegroupthatwouldneverexist', 'New Group');
|
|
|
|
$this->assertEquals($grouplessMember->Groups()->Count(), 2);
|
|
|
|
|
|
|
|
$group = DataObject::get_one('Group', "\"Code\" = 'somegroupthatwouldneverexist'");
|
|
|
|
$this->assertNotNull($group);
|
|
|
|
$this->assertEquals($group->Code, 'somegroupthatwouldneverexist');
|
|
|
|
$this->assertEquals($group->Title, 'New Group');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testInGroup() {
|
2008-11-03 02:57:16 +01:00
|
|
|
$staffmember = $this->objFromFixture('Member', 'staffmember');
|
|
|
|
$managementmember = $this->objFromFixture('Member', 'managementmember');
|
|
|
|
$accountingmember = $this->objFromFixture('Member', 'accountingmember');
|
|
|
|
$ceomember = $this->objFromFixture('Member', 'ceomember');
|
|
|
|
|
|
|
|
$staffgroup = $this->objFromFixture('Group', 'staffgroup');
|
|
|
|
$managementgroup = $this->objFromFixture('Group', 'managementgroup');
|
|
|
|
$accountinggroup = $this->objFromFixture('Group', 'accountinggroup');
|
|
|
|
$ceogroup = $this->objFromFixture('Group', 'ceogroup');
|
|
|
|
|
|
|
|
$this->assertTrue(
|
|
|
|
$staffmember->inGroup($staffgroup),
|
|
|
|
'Direct group membership is detected'
|
|
|
|
);
|
|
|
|
$this->assertTrue(
|
|
|
|
$managementmember->inGroup($staffgroup),
|
|
|
|
'Users of child group are members of a direct parent group (if not in strict mode)'
|
|
|
|
);
|
|
|
|
$this->assertTrue(
|
|
|
|
$accountingmember->inGroup($staffgroup),
|
|
|
|
'Users of child group are members of a direct parent group (if not in strict mode)'
|
|
|
|
);
|
|
|
|
$this->assertTrue(
|
|
|
|
$ceomember->inGroup($staffgroup),
|
|
|
|
'Users of indirect grandchild group are members of a parent group (if not in strict mode)'
|
|
|
|
);
|
|
|
|
$this->assertTrue(
|
|
|
|
$ceomember->inGroup($ceogroup, true),
|
|
|
|
'Direct group membership is dected (if in strict mode)'
|
|
|
|
);
|
|
|
|
$this->assertFalse(
|
|
|
|
$ceomember->inGroup($staffgroup, true),
|
|
|
|
'Users of child group are not members of a direct parent group (if in strict mode)'
|
|
|
|
);
|
|
|
|
$this->assertFalse(
|
|
|
|
$staffmember->inGroup($managementgroup),
|
|
|
|
'Users of parent group are not members of a direct child group'
|
|
|
|
);
|
|
|
|
$this->assertFalse(
|
|
|
|
$staffmember->inGroup($ceogroup),
|
|
|
|
'Users of parent group are not members of an indirect grandchild group'
|
|
|
|
);
|
|
|
|
$this->assertFalse(
|
|
|
|
$accountingmember->inGroup($managementgroup),
|
|
|
|
'Users of group are not members of any siblings'
|
|
|
|
);
|
2009-04-29 02:07:39 +02:00
|
|
|
$this->assertFalse(
|
|
|
|
$staffmember->inGroup('does-not-exist'),
|
|
|
|
'Non-existant group returns false'
|
|
|
|
);
|
2008-11-03 02:57:16 +01:00
|
|
|
}
|
2010-10-19 04:46:26 +02:00
|
|
|
|
2009-12-16 06:39:39 +01:00
|
|
|
/**
|
|
|
|
* Tests that the user is able to view their own record, and in turn, they can
|
|
|
|
* edit and delete their own record too.
|
|
|
|
*/
|
|
|
|
public function testCanManipulateOwnRecord() {
|
|
|
|
$extensions = $this->removeExtensions(Object::get_extensions('Member'));
|
|
|
|
$member = $this->objFromFixture('Member', 'test');
|
|
|
|
$member2 = $this->objFromFixture('Member', 'staffmember');
|
|
|
|
|
|
|
|
$this->session()->inst_set('loggedInAs', null);
|
|
|
|
|
|
|
|
/* Not logged in, you can't view, delete or edit the record */
|
|
|
|
$this->assertFalse($member->canView());
|
|
|
|
$this->assertFalse($member->canDelete());
|
|
|
|
$this->assertFalse($member->canEdit());
|
|
|
|
|
|
|
|
/* Logged in users can edit their own record */
|
|
|
|
$this->session()->inst_set('loggedInAs', $member->ID);
|
|
|
|
$this->assertTrue($member->canView());
|
|
|
|
$this->assertTrue($member->canDelete());
|
|
|
|
$this->assertTrue($member->canEdit());
|
|
|
|
|
|
|
|
/* Other uses cannot view, delete or edit others records */
|
|
|
|
$this->session()->inst_set('loggedInAs', $member2->ID);
|
|
|
|
$this->assertFalse($member->canView());
|
|
|
|
$this->assertFalse($member->canDelete());
|
|
|
|
$this->assertFalse($member->canEdit());
|
2010-10-19 04:46:26 +02:00
|
|
|
|
2009-12-16 06:39:39 +01:00
|
|
|
$this->addExtensions($extensions);
|
|
|
|
$this->session()->inst_set('loggedInAs', null);
|
|
|
|
}
|
2010-10-19 04:46:26 +02:00
|
|
|
|
2009-12-16 06:39:39 +01:00
|
|
|
public function testAuthorisedMembersCanManipulateOthersRecords() {
|
|
|
|
$extensions = $this->removeExtensions(Object::get_extensions('Member'));
|
|
|
|
$member = $this->objFromFixture('Member', 'test');
|
|
|
|
$member2 = $this->objFromFixture('Member', 'staffmember');
|
|
|
|
|
|
|
|
/* Group members with SecurityAdmin permissions can manipulate other records */
|
|
|
|
$this->session()->inst_set('loggedInAs', $member->ID);
|
|
|
|
$this->assertTrue($member2->canView());
|
|
|
|
$this->assertTrue($member2->canDelete());
|
|
|
|
$this->assertTrue($member2->canEdit());
|
|
|
|
|
|
|
|
$this->addExtensions($extensions);
|
|
|
|
$this->session()->inst_set('loggedInAs', null);
|
|
|
|
}
|
2010-10-19 04:46:26 +02:00
|
|
|
|
2011-04-15 11:35:30 +02:00
|
|
|
public function testExtendedCan() {
|
2009-12-16 06:39:57 +01:00
|
|
|
$extensions = $this->removeExtensions(Object::get_extensions('Member'));
|
|
|
|
$member = $this->objFromFixture('Member', 'test');
|
|
|
|
|
|
|
|
/* Normal behaviour is that you can't view a member unless canView() on an extension returns true */
|
|
|
|
$this->assertFalse($member->canView());
|
|
|
|
$this->assertFalse($member->canDelete());
|
|
|
|
$this->assertFalse($member->canEdit());
|
|
|
|
|
2011-04-15 11:35:30 +02:00
|
|
|
/* Apply a extension that allows viewing in any case (most likely the case for member profiles) */
|
2009-12-16 06:39:57 +01:00
|
|
|
Object::add_extension('Member', 'MemberTest_ViewingAllowedExtension');
|
|
|
|
$member2 = $this->objFromFixture('Member', 'staffmember');
|
|
|
|
|
|
|
|
$this->assertTrue($member2->canView());
|
|
|
|
$this->assertFalse($member2->canDelete());
|
|
|
|
$this->assertFalse($member2->canEdit());
|
2010-10-19 04:46:26 +02:00
|
|
|
|
2011-04-15 11:35:30 +02:00
|
|
|
/* Apply a extension that denies viewing of the Member */
|
2009-12-16 06:39:57 +01:00
|
|
|
Object::remove_extension('Member', 'MemberTest_ViewingAllowedExtension');
|
|
|
|
Object::add_extension('Member', 'MemberTest_ViewingDeniedExtension');
|
|
|
|
$member3 = $this->objFromFixture('Member', 'managementmember');
|
|
|
|
|
|
|
|
$this->assertFalse($member3->canView());
|
|
|
|
$this->assertFalse($member3->canDelete());
|
|
|
|
$this->assertFalse($member3->canEdit());
|
2010-10-19 04:46:26 +02:00
|
|
|
|
2011-04-15 11:35:30 +02:00
|
|
|
/* Apply a extension that allows viewing and editing but denies deletion */
|
2009-12-16 06:39:57 +01:00
|
|
|
Object::remove_extension('Member', 'MemberTest_ViewingDeniedExtension');
|
|
|
|
Object::add_extension('Member', 'MemberTest_EditingAllowedDeletingDeniedExtension');
|
|
|
|
$member4 = $this->objFromFixture('Member', 'accountingmember');
|
|
|
|
|
|
|
|
$this->assertTrue($member4->canView());
|
|
|
|
$this->assertFalse($member4->canDelete());
|
|
|
|
$this->assertTrue($member4->canEdit());
|
|
|
|
|
|
|
|
Object::remove_extension('Member', 'MemberTest_EditingAllowedDeletingDeniedExtension');
|
|
|
|
$this->addExtensions($extensions);
|
|
|
|
}
|
2010-10-19 04:46:26 +02:00
|
|
|
|
2010-10-19 03:24:04 +02:00
|
|
|
/**
|
|
|
|
* Tests for {@link Member::getName()} and {@link Member::setName()}
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testName() {
|
2010-10-19 03:24:04 +02:00
|
|
|
$member = $this->objFromFixture('Member', 'test');
|
|
|
|
$member->setName('Test Some User');
|
|
|
|
$this->assertEquals('Test Some User', $member->getName());
|
|
|
|
$member->setName('Test');
|
|
|
|
$this->assertEquals('Test', $member->getName());
|
|
|
|
$member->FirstName = 'Test';
|
|
|
|
$member->Surname = '';
|
|
|
|
$this->assertEquals('Test', $member->getName());
|
|
|
|
}
|
2010-10-19 04:46:26 +02:00
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testMembersWithSecurityAdminAccessCantEditAdminsUnlessTheyreAdminsThemselves() {
|
2010-10-19 04:46:26 +02:00
|
|
|
$adminMember = $this->objFromFixture('Member', 'admin');
|
|
|
|
$otherAdminMember = $this->objFromFixture('Member', 'other-admin');
|
|
|
|
$securityAdminMember = $this->objFromFixture('Member', 'test');
|
|
|
|
$ceoMember = $this->objFromFixture('Member', 'ceomember');
|
|
|
|
|
|
|
|
// Careful: Don't read as english language.
|
|
|
|
// More precisely this should read canBeEditedBy()
|
|
|
|
|
|
|
|
$this->assertTrue($adminMember->canEdit($adminMember), 'Admins can edit themselves');
|
|
|
|
$this->assertTrue($otherAdminMember->canEdit($adminMember), 'Admins can edit other admins');
|
|
|
|
$this->assertTrue($securityAdminMember->canEdit($adminMember), 'Admins can edit other members');
|
|
|
|
|
|
|
|
$this->assertTrue($securityAdminMember->canEdit($securityAdminMember), 'Security-Admins can edit themselves');
|
|
|
|
$this->assertFalse($adminMember->canEdit($securityAdminMember), 'Security-Admins can not edit other admins');
|
|
|
|
$this->assertTrue($ceoMember->canEdit($securityAdminMember), 'Security-Admins can edit other members');
|
|
|
|
}
|
2011-03-09 03:49:41 +01:00
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testOnChangeGroups() {
|
2011-03-09 03:49:41 +01:00
|
|
|
$staffGroup = $this->objFromFixture('Group', 'staffgroup');
|
|
|
|
$adminGroup = $this->objFromFixture('Group', 'admingroup');
|
|
|
|
$staffMember = $this->objFromFixture('Member', 'staffmember');
|
|
|
|
$adminMember = $this->objFromFixture('Member', 'admin');
|
|
|
|
$newAdminGroup = new Group(array('Title' => 'newadmin'));
|
|
|
|
$newAdminGroup->write();
|
|
|
|
Permission::grant($newAdminGroup->ID, 'ADMIN');
|
|
|
|
$newOtherGroup = new Group(array('Title' => 'othergroup'));
|
|
|
|
$newOtherGroup->write();
|
|
|
|
|
|
|
|
$this->assertTrue(
|
|
|
|
$staffMember->onChangeGroups(array($staffGroup->ID)),
|
|
|
|
'Adding existing non-admin group relation is allowed for non-admin members'
|
|
|
|
);
|
|
|
|
$this->assertTrue(
|
|
|
|
$staffMember->onChangeGroups(array($newOtherGroup->ID)),
|
|
|
|
'Adding new non-admin group relation is allowed for non-admin members'
|
|
|
|
);
|
|
|
|
$this->assertFalse(
|
|
|
|
$staffMember->onChangeGroups(array($newAdminGroup->ID)),
|
|
|
|
'Adding new admin group relation is not allowed for non-admin members'
|
|
|
|
);
|
2012-04-27 02:22:58 +02:00
|
|
|
|
|
|
|
$this->session()->inst_set('loggedInAs', $adminMember->ID);
|
|
|
|
$this->assertTrue(
|
|
|
|
$staffMember->onChangeGroups(array($newAdminGroup->ID)),
|
|
|
|
'Adding new admin group relation is allowed for normal users, when granter is logged in as admin'
|
|
|
|
);
|
|
|
|
$this->session()->inst_set('loggedInAs', null);
|
|
|
|
|
2011-03-09 03:49:41 +01:00
|
|
|
$this->assertTrue(
|
|
|
|
$adminMember->onChangeGroups(array($newAdminGroup->ID)),
|
|
|
|
'Adding new admin group relation is allowed for admin members'
|
|
|
|
);
|
|
|
|
}
|
2012-05-10 03:53:45 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Test that all members are returned
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testMap_in_groupsReturnsAll() {
|
2012-05-10 03:53:45 +02:00
|
|
|
$members = Member::map_in_groups();
|
|
|
|
$this->assertEquals(13, count($members), 'There are 12 members in the mock plus a fake admin');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test that only admin members are returned
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function testMap_in_groupsReturnsAdmins() {
|
2012-05-10 03:53:45 +02:00
|
|
|
$adminID = $this->objFromFixture('Group', 'admingroup')->ID;
|
|
|
|
$members = Member::map_in_groups($adminID);
|
|
|
|
|
|
|
|
$admin = $this->objFromFixture('Member', 'admin');
|
|
|
|
$otherAdmin = $this->objFromFixture('Member', 'other-admin');
|
|
|
|
|
2012-09-26 23:34:00 +02:00
|
|
|
$this->assertTrue(in_array($admin->getTitle(), $members),
|
|
|
|
$admin->getTitle().' should be in the returned list.');
|
|
|
|
$this->assertTrue(in_array($otherAdmin->getTitle(), $members),
|
|
|
|
$otherAdmin->getTitle().' should be in the returned list.');
|
2012-05-10 03:53:45 +02:00
|
|
|
$this->assertEquals(2, count($members), 'There should be 2 members from the admin group');
|
|
|
|
}
|
2010-10-19 03:24:04 +02:00
|
|
|
|
2009-12-16 06:39:39 +01:00
|
|
|
/**
|
|
|
|
* Add the given array of member extensions as class names.
|
|
|
|
* This is useful for re-adding extensions after being removed
|
|
|
|
* in a test case to produce an unbiased test.
|
|
|
|
*
|
|
|
|
* @param array $extensions
|
|
|
|
* @return array The added extensions
|
|
|
|
*/
|
|
|
|
protected function addExtensions($extensions) {
|
|
|
|
if($extensions) foreach($extensions as $extension) {
|
|
|
|
Object::add_extension('Member', $extension);
|
|
|
|
}
|
|
|
|
return $extensions;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove given extensions from Member. This is useful for
|
|
|
|
* removing extensions that could produce a biased
|
|
|
|
* test result, as some extensions applied by project
|
|
|
|
* code or modules can do this.
|
|
|
|
*
|
|
|
|
* @param array $extensions
|
|
|
|
* @return array The removed extensions
|
|
|
|
*/
|
|
|
|
protected function removeExtensions($extensions) {
|
|
|
|
if($extensions) foreach($extensions as $extension) {
|
|
|
|
Object::remove_extension('Member', $extension);
|
|
|
|
}
|
|
|
|
return $extensions;
|
|
|
|
}
|
|
|
|
|
2012-11-08 04:33:19 +01:00
|
|
|
public function testGenerateAutologinTokenAndStoreHash() {
|
|
|
|
$enc = new PasswordEncryptor_Blowfish();
|
|
|
|
|
|
|
|
$m = new Member();
|
|
|
|
$m->PasswordEncryption = 'blowfish';
|
|
|
|
$m->Salt = $enc->salt('123');
|
|
|
|
|
|
|
|
$token = $m->generateAutologinTokenAndStoreHash();
|
|
|
|
|
|
|
|
$this->assertEquals($m->encryptWithUserSettings($token), $m->AutoLoginHash, 'Stores the token as ahash.');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testValidateAutoLoginToken() {
|
|
|
|
$enc = new PasswordEncryptor_Blowfish();
|
|
|
|
|
|
|
|
$m1 = new Member();
|
|
|
|
$m1->PasswordEncryption = 'blowfish';
|
|
|
|
$m1->Salt = $enc->salt('123');
|
|
|
|
$m1Token = $m1->generateAutologinTokenAndStoreHash();
|
|
|
|
|
|
|
|
$m2 = new Member();
|
|
|
|
$m2->PasswordEncryption = 'blowfish';
|
|
|
|
$m2->Salt = $enc->salt('456');
|
|
|
|
$m2Token = $m2->generateAutologinTokenAndStoreHash();
|
|
|
|
|
|
|
|
$this->assertTrue($m1->validateAutoLoginToken($m1Token), 'Passes token validity test against matching member.');
|
|
|
|
$this->assertFalse($m2->validateAutoLoginToken($m1Token), 'Fails token validity test against other member.');
|
|
|
|
}
|
|
|
|
|
2009-12-16 06:39:57 +01:00
|
|
|
}
|
2011-04-15 11:35:30 +02:00
|
|
|
class MemberTest_ViewingAllowedExtension extends DataExtension implements TestOnly {
|
2009-12-16 06:39:57 +01:00
|
|
|
|
2012-03-27 06:04:11 +02:00
|
|
|
public function canView($member = null) {
|
2009-12-16 06:39:57 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2011-04-15 11:35:30 +02:00
|
|
|
class MemberTest_ViewingDeniedExtension extends DataExtension implements TestOnly {
|
2009-12-16 06:39:57 +01:00
|
|
|
|
2012-03-27 06:04:11 +02:00
|
|
|
public function canView($member = null) {
|
2009-12-16 06:39:57 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2011-04-15 11:35:30 +02:00
|
|
|
class MemberTest_EditingAllowedDeletingDeniedExtension extends DataExtension implements TestOnly {
|
2009-12-16 06:39:57 +01:00
|
|
|
|
2012-03-27 06:04:11 +02:00
|
|
|
public function canView($member = null) {
|
2009-12-16 06:39:57 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-03-27 06:04:11 +02:00
|
|
|
public function canEdit($member = null) {
|
2009-12-16 06:39:57 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-03-27 06:04:11 +02:00
|
|
|
public function canDelete($member = null) {
|
2009-12-16 06:39:57 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-03-02 00:28:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
class MemberTest_PasswordValidator extends PasswordValidator {
|
2012-09-19 12:07:39 +02:00
|
|
|
public function __construct() {
|
2012-03-02 00:28:04 +01:00
|
|
|
parent::__construct();
|
|
|
|
$this->minLength(7);
|
|
|
|
$this->checkHistoricalPasswords(6);
|
|
|
|
$this->characterStrength(3, array('lowercase','uppercase','digits','punctuation'));
|
|
|
|
}
|
|
|
|
|
2012-03-09 05:28:28 +01:00
|
|
|
}
|