fix: Use file-based session until database is migrated

- Prevents circular dependency where login requires session, but session requires database table created by migrations
- Fresh installs: use file session until migrations run, then switch to database session
- Upgrades: use file session during migration, then switch to database session
- Ensures sessions table exists before using database session handler

Fixes: Sessions table missing on fresh install prevents login
This commit is contained in:
Ollama
2026-04-01 21:17:00 +00:00
parent 56670271d6
commit cb020f6219

View File

@@ -4,7 +4,9 @@ namespace App\Events;
use App\Libraries\MY_Migration;
use App\Models\Appconfig;
use CodeIgniter\Session\Handlers\FileHandler;
use CodeIgniter\Session\Session;
use Config\Database;
use Config\OSPOS;
use Config\Services;
@@ -28,7 +30,8 @@ class Load_config
$migration_config = config('Migrations');
$migration = new MY_Migration($migration_config);
$this->session = session();
// Use file-based session until database is ready
$this->session = $this->createSession($migration->is_latest());
// Database Configuration
$config = config(OSPOS::class);
@@ -53,4 +56,66 @@ class Load_config
bcscale(max(2, totals_decimals() + tax_decimals()));
}
/**
* Creates session with appropriate handler.
* Uses file-based session until database is migrated, then switches to database session.
*/
private function createSession(bool $isDbMigrated): Session
{
$sessionConfig = config('Session');
// If database is migrated and database sessions are configured, ensure table exists
if ($isDbMigrated && $sessionConfig->driver === \CodeIgniter\Session\Handlers\DatabaseHandler::class) {
$this->ensureSessionsTableExists();
}
// If database is not ready, temporarily use file-based session
if (!$isDbMigrated && $sessionConfig->driver === \CodeIgniter\Session\Handlers\DatabaseHandler::class) {
$sessionConfig->driver = FileHandler::class;
$sessionConfig->savePath = WRITEPATH . 'session';
}
return Services::session($sessionConfig);
}
/**
* Ensures the sessions table exists for database session handler.
*/
private function ensureSessionsTableExists(): void
{
$db = Database::connect();
if (!$db->tableExists('sessions')) {
$forge = Database::forge();
$forge->addField([
'id' => ['type' => 'varchar', 'constraint' => 128],
'ip_address' => ['type' => 'varchar', 'constraint' => 45],
'timestamp' => ['type' => 'timestamp', 'default' => 'CURRENT_TIMESTAMP'],
'data' => ['type' => 'blob'],
]);
$forge->addKey('timestamp');
$forge->createTable('sessions', true);
if (!$this->primaryKeyExists('sessions')) {
$db->query('ALTER TABLE ' . $db->getPrefix() . 'sessions ADD PRIMARY KEY (id, ip_address)');
}
}
}
/**
* Checks if a primary key exists on the sessions table.
*/
private function primaryKeyExists(string $tableName): bool
{
$db = Database::connect();
$result = $db->query(
'SELECT COUNT(*) as count FROM information_schema.table_constraints ' .
'WHERE table_schema = DATABASE() ' .
'AND table_name = \'' . $db->getPrefix() . $tableName . '\' ' .
'AND constraint_type = \'PRIMARY KEY\''
);
$row = $result->getRow();
return $row && $row->count > 0;
}
}