/** * @return array */ private function artefacts() { $oldschema = []; $newschema = []; $current = DB::get_conn()->getSelectedDatabase(); foreach (DB::table_list() as $lowercase => $dbtablename) { $oldschema[$dbtablename] = DB::field_list($dbtablename); } $test = new SapphireTest(); $test->create_temp_db(); foreach (DB::table_list() as $lowercase => $dbtablename) { $newschema[$lowercase] = DB::field_list($dbtablename); } $test->kill_temp_db(); DB::get_conn()->selectDatabase($current); $artefacts = []; foreach ($oldschema as $table => $fields) { if (!isset($newschema[strtolower($table)])) { $artefacts[$table] = $table; continue; } foreach ($fields as $field => $spec) { if (!isset($newschema[strtolower($table)][$field])) { $artefacts[$table][$field] = $field; } } } return $artefacts; }
/** * Migrations for GroupSubsites data. */ public function requireDefaultRecords() { // Migration for Group.SubsiteID data from when Groups only had a single subsite $groupFields = DB::field_list('Group'); // Detection of SubsiteID field is the trigger for old-style-subsiteID migration if (isset($groupFields['SubsiteID'])) { // Migrate subsite-specific data DB::query('INSERT INTO "Group_Subsites" ("GroupID", "SubsiteID") SELECT "ID", "SubsiteID" FROM "Group" WHERE "SubsiteID" > 0'); // Migrate global-access data DB::query('UPDATE "Group" SET "AccessAllSubsites" = 1 WHERE "SubsiteID" = 0'); // Move the field out of the way so that this migration doesn't get executed again DB::get_schema()->renameField('Group', 'SubsiteID', '_obsolete_SubsiteID'); // No subsite access on anything means that we've just installed the subsites module. // Make all previous groups global-access groups } elseif (!DB::query('SELECT "Group"."ID" FROM "Group" LEFT JOIN "Group_Subsites" ON "Group_Subsites"."GroupID" = "Group"."ID" AND "Group_Subsites"."SubsiteID" > 0 WHERE "AccessAllSubsites" = 1 OR "Group_Subsites"."GroupID" IS NOT NULL ')->value()) { DB::query('UPDATE "Group" SET "AccessAllSubsites" = 1'); } }
/** * 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() { // Used for unit tests if (self::$force_database_is_ready !== NULL) { return self::$force_database_is_ready; } if (self::$database_is_ready) { return self::$database_is_ready; } $requiredTables = ClassInfo::dataClassesFor('Member'); $requiredTables[] = 'Group'; $requiredTables[] = 'Permission'; foreach ($requiredTables as $table) { // Skip test classes, as not all test classes are scaffolded at once if (is_subclass_of($table, 'TestOnly')) { continue; } // if any of the tables aren't created in the database if (!ClassInfo::hasTable($table)) { return false; } // HACK: DataExtensions aren't applied until a class is instantiated for // the first time, so create an instance here. singleton($table); // if any of the tables don't have all fields mapped as table columns $dbFields = DB::field_list($table); if (!$dbFields) { return false; } $objFields = DataObject::database_fields($table, false); $missingFields = array_diff_key($objFields, $dbFields); if ($missingFields) { return false; } } self::$database_is_ready = true; return true; }
/** * Logs this member in * * @param bool $remember If set to TRUE, the member will be logged in automatically the next time. */ public function logIn($remember = false) { $this->extend('beforeMemberLoggedIn'); self::session_regenerate_id(); Session::set("loggedInAs", $this->ID); // This lets apache rules detect whether the user has logged in if (Member::config()->login_marker_cookie) { Cookie::set(Member::config()->login_marker_cookie, 1, 0); } if ($remember) { // Store the hash and give the client the cookie with the token. $generator = new RandomGenerator(); $token = $generator->randomToken('sha1'); $hash = $this->encryptWithUserSettings($token); $this->RememberLoginToken = $hash; Cookie::set('alc_enc', $this->ID . ':' . $token, 90, null, null, null, true); } else { $this->RememberLoginToken = null; Cookie::force_expiry('alc_enc'); } // Clear the incorrect log-in count $this->registerSuccessfulLogin(); // Don't set column if its not built yet (the login might be precursor to a /dev/build...) if (array_key_exists('LockedOutUntil', DB::field_list('Member'))) { $this->LockedOutUntil = null; } $this->regenerateTempID(); $this->write(); // Audit logging hook $this->extend('memberLoggedIn'); }
/** * Logs this member in * * @param bool $remember If set to TRUE, the member will be logged in automatically the next time. */ public function logIn($remember = false) { $this->extend('beforeMemberLoggedIn'); self::session_regenerate_id(); Session::set("loggedInAs", $this->ID); // This lets apache rules detect whether the user has logged in if (Member::config()->login_marker_cookie) { Cookie::set(Member::config()->login_marker_cookie, 1, 0); } // Cleans up any potential previous hash for this member on this device if ($alcDevice = Cookie::get('alc_device')) { RememberLoginHash::get()->filter('DeviceID', $alcDevice)->removeAll(); } if ($remember) { $rememberLoginHash = RememberLoginHash::generate($this); $tokenExpiryDays = Config::inst()->get('RememberLoginHash', 'token_expiry_days'); $deviceExpiryDays = Config::inst()->get('RememberLoginHash', 'device_expiry_days'); Cookie::set('alc_enc', $this->ID . ':' . $rememberLoginHash->getToken(), $tokenExpiryDays, null, null, null, true); Cookie::set('alc_device', $rememberLoginHash->DeviceID, $deviceExpiryDays, null, null, null, true); } else { Cookie::set('alc_enc', null); Cookie::set('alc_device', null); Cookie::force_expiry('alc_enc'); Cookie::force_expiry('alc_device'); } // Clear the incorrect log-in count $this->registerSuccessfulLogin(); // Don't set column if its not built yet (the login might be precursor to a /dev/build...) if (array_key_exists('LockedOutUntil', DB::field_list('Member'))) { $this->LockedOutUntil = null; } $this->regenerateTempID(); $this->write(); // Audit logging hook $this->extend('memberLoggedIn'); }