diff --git a/security/Security.php b/security/Security.php index 2f2e5b660..afbcfdf80 100644 --- a/security/Security.php +++ b/security/Security.php @@ -826,6 +826,8 @@ class Security extends Controller { /** * Checks the database is in a state to perform security checks. + * See {@link DatabaseAdmin->init()} for more information. + * * @return bool */ public static function database_is_ready() { @@ -833,10 +835,21 @@ class Security extends Controller { $requiredTables[] = 'Group'; $requiredTables[] = 'Permission'; - foreach($requiredTables as $table) if(!ClassInfo::hasTable($table)) return false; + foreach($requiredTables as $table) { + // if any of the tables aren't created in the database + if(!ClassInfo::hasTable($table)) return false; - return (($permissionFields = DB::fieldList('Permission')) && isset($permissionFields['Type'])) && - (($memberFields = DB::fieldList('Member')) && isset($memberFields['RememberLoginToken'])); + // if any of the tables don't have all fields mapped as table columns + $dbFields = DB::fieldList($table); + if(!$dbFields) return false; + + $objFields = DataObject::database_fields($table); + $missingFields = array_diff_key($objFields, $dbFields); + + if($missingFields) return false; + } + + return true; } /** diff --git a/tests/security/SecurityTest.php b/tests/security/SecurityTest.php index e5608ed43..37d7ef7e7 100644 --- a/tests/security/SecurityTest.php +++ b/tests/security/SecurityTest.php @@ -260,6 +260,19 @@ class SecurityTest extends FunctionalTest { $this->assertEquals($attempt->Email, 'sam@silverstripe.com'); $this->assertEquals($attempt->Member(), $member); } + + function testDatabaseIsReadyWithInsufficientMemberColumns() { + // Assumption: The database has been built correctly by the test runner, + // and has all columns present in the ORM + DB::getConn()->renameField('Member', 'Email', 'Email_renamed'); + + // Email column is now missing, which means we're not ready to do permission checks + $this->assertFalse(Security::database_is_ready()); + + // Rebuild the database (which re-adds the Email column), and try again + $this->resetDBSchema(true); + $this->assertTrue(Security::database_is_ready()); + } /** * Execute a log-in form using Director::test().