You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
PlexShare/fuel/packages/auth/tasks/simple2orm.php

442 lines
13 KiB

<?php
/**
* Fuel is a fast, lightweight, community driven PHP 5.4+ framework.
*
* @package Fuel
* @version 1.8.1
* @author Fuel Development Team
* @license MIT License
* @copyright 2010 - 2018 Fuel Development Team
* @link http://fuelphp.com
*/
namespace Fuel\Tasks;
/**
* Converts a SimpleAuth ruleset to an OrmAuth one
*/
class Simple2orm
{
/*
* @var array collected data during validation
*/
protected static $data = array();
/**
* Show help.
*
* Usage (from command line):
*
* php oil refine simple2orm
*/
public static function run()
{
// fetch the commandline options
$run_migration = \Cli::option('migrate', \Cli::option('m', false));
$run_validation = $run_migration ? true : \Cli::option('validate', \Cli::option('v', false));
// if no run options are present, show the help
if ( ! $run_migration and ! $run_validation )
{
return static::help();
}
// step 1: run validation
$validated = true;
if ($run_validation)
{
$validated = static::run_validation();
}
// step 2: run migration
if ($run_migration)
{
if ($validated)
{
$migrated = static::run_migration();
if ($migrated)
{
\Cli::write('Migration succesfully finished', 'light_green');
}
else
{
\Cli::write("\n".'Migration failed. Skipping the remainder of the migration. Please correct the errors and run again.', 'light_red');
}
}
else
{
\Cli::write("\n".'Validation failed. Skipping the actual migration. Please correct the errors.', 'light_red');
}
}
}
/**
* Show help.
*
* Usage (from command line):
*
* php oil refine simple2orm:help
*/
public static function help()
{
$output = <<<HELP
Description:
The task converts an existing SimpleAuth setup to OrmAuth, migrating
all configured users, groups, roles and rights.
Before using this task, make sure your auth configuration is set to use
the Ormauth driver, you have an ormauth configuration file, and you have
run all auth migrations.
Runtime options:
-v, [--validate] # Validate the current installation, do not migrate
-m, [--migrate] # Run the migration
Commands:
php oil refine simple2orm
php oil refine simple2orm:help
php oil refine simple2orm --validate
php oil refine simple2orm
HELP;
\Cli::write($output);
}
/**
* Run the environment validation
*/
protected static function run_validation()
{
// storage for collected errors
$errors = array();
// validate the auth configuration file
if ( ! is_file($file = APPPATH.'config'.DS.'auth.php'))
{
$errors[] = \Fuel::clean_path($file).' does not exist.';
}
else
{
\Config::load('auth', true);
if ( ! $driver = \Config::get('auth.driver', false))
{
$errors[] = \Fuel::clean_path($file).' does not define an auth driver.';
}
elseif ($driver != 'Ormauth')
{
$errors[] = \Fuel::clean_path($file).' is not configured to use the Ormauth driver.';
}
}
// validate the simpleauth configuration file
if ( ! is_file($file = APPPATH.'config'.DS.'simpleauth.php'))
{
$errors[] = \Fuel::clean_path($file).' does not exist.';
}
else
{
\Config::load('simpleauth', true);
if ( ! $table = \Config::get('simpleauth.table_name', false))
{
$errors[] = \Fuel::clean_path($file).' does not define a user table.';
}
elseif ( ! \DBUtil::table_exists($table))
{
$errors[] = \Fuel::clean_path($file).' defines a table that does not exist.';
}
else
{
// store the table name for future use
static::$data['simpleauth_table'] = $table;
}
}
// validate the ormauth configuration file
if ( ! is_file($file = APPPATH.'config'.DS.'ormauth.php'))
{
$errors[] = \Fuel::clean_path($file).' does not exist.';
}
else
{
$config = \Config::load('ormauth', true);
if ( ! $table = \Config::get('ormauth.table_name', false))
{
$errors[] = \Fuel::clean_path($file).' does not define a user table.';
}
elseif ( ! \DBUtil::table_exists($table))
{
$errors[] = \Fuel::clean_path($file).' defines a table that does not exist.';
}
else
{
// store the table name for future use
static::$data['ormauth_table'] = $table;
}
if ( ! $cache_prefix = \Config::get('ormauth.cache_prefix', false) or empty($cache_prefix))
{
$errors[] = \Fuel::clean_path($file).' does not define a cache_prefix.';
}
else
{
// store the cache prefix for future use
static::$data['cache_prefix'] = $cache_prefix;
}
}
// check if all migrations have run, and the migration system is consistent
$migrations = \Config::load('migrations', true);
if ( ! isset($migrations['version']['package']['auth'][6]))
{
$errors[] = 'Auth database migrations haven\'t run (succesfully).';
}
else
{
$result = \DB::select('*')->from($migrations['table'])->where('type', '=', 'package')->where('name', '=', 'auth')->execute();
if (count($result) < 7)
{
$errors[] = 'Auth database migrations haven\'t run (succesfully).';
$errors[] = 'There is a discrepancy between your migration configuration file and the migration table.';
}
}
// check the fields of the users table
$usertable = array(
'id' => array('type' => 'int', 'constraint' => 11, 'auto_increment' => true),
'username' => array('type' => 'varchar', 'constraint' => 50, 'after' => 'id'),
'password' => array('type' => 'varchar', 'constraint' => 255, 'after' => 'username'),
'group_id' => array('type' => 'int', 'constraint' => 11, 'default' => 1, 'after' => 'password'),
'email' => array('type' => 'varchar', 'constraint' => 255, 'after' => 'group_id'),
'last_login' => array('type' => 'varchar', 'constraint' => 25, 'after' => 'email'),
'previous_login' => array('type' => 'varchar', 'constraint' => 25, 'default' => 0, 'after' => 'last_login'),
'login_hash' => array('type' => 'varchar', 'constraint' => 255, 'after' => 'previous_login'),
'user_id' => array('type' => 'int', 'constraint' => 11, 'default' => 0, 'after' => 'login_hash'),
'created_at' => array('type' => 'int', 'constraint' => 11, 'default' => 0, 'after' => 'user_id'),
'updated_at' => array('type' => 'int', 'constraint' => 11, 'default' => 0, 'after' => 'created_at'),
);
foreach ($usertable as $field => $value)
{
if (\DBUtil::field_exists(static::$data['ormauth_table'], $field))
{
unset($usertable[$field]);
}
}
if ( ! empty($usertable))
{
$errors[] = 'User table "'.static::$data['ormauth_table'].'" is missing the field(s): '.implode(', ', array_keys($usertable));
}
// process the results of the validation
if ($errors)
{
// display all errors
\Cli::write('You environment did not validate:', 'light_red');
foreach ($errors as $error)
{
\Cli::write('* '.$error);
}
return false;
}
// inform the user we're good to go
\Cli::write('Environment validated', 'light_green');
return true;
}
/**
* Run the actual migration
*/
protected static function run_migration()
{
// make sure we've got a usertable we can work with
static::usertable();
// get the simpleauth config
\Config::load('simpleauth', true);
$simpleauth = \Config::get('simpleauth', array());
// process the defined roles
foreach (\Config::get('simpleauth.roles', array()) as $role => $config)
{
// skip all non-standard roles
if ($role == '#' or ! is_array($config))
{
continue;
}
// do we already have this role?
$result = \DB::select('id')->from(static::$data['ormauth_table'].'_roles')->where('name', '=', $role)->execute();
if (count($result))
{
$role_id = $result[0]['id'];
}
// no, add it
else
{
\Cli::write('- creating role: '.$role, 'light_green');
list($role_id, $rows_affected) = \DB::insert(static::$data['ormauth_table'].'_roles')->set(array('name' => $role))->execute();
}
// fetch the role as an ORM object, and assign the defined permissions to it
$role = \Model\Auth_Role::find($role_id);
if ($role)
{
foreach ($config as $area => $permissions)
{
foreach ($permissions as $permission)
{
$perm = \Model\Auth_Permission::query()->where('area', '=', $area)->where('permission', '=', $permission)->get_one();
if ( ! $perm)
{
\Cli::write('- creating permission: '.$area.'.'.$permission, 'light_green');
$perm = \Model\Auth_Permission::forge(array('area' => $area, 'permission' => $permission, 'description' => $area.'.'.$permission, 'actions' => serialize(array())));
}
$role->permissions[] = $perm;
}
}
// update the role and save the permissions
$role->save();
}
}
// process the defined groups
foreach (\Config::get('simpleauth.groups', array()) as $group => $config)
{
// ignore invalid entries
if ( ! isset($config['name']) or ! isset($config['roles']))
{
continue;
}
// do we already have this group?
$result = \DB::select('id')->from(static::$data['ormauth_table'].'_groups')->where('name', '=', $config['name'])->execute();
if (count($result))
{
$group_id = $result[0]['id'];
}
// no, add it
else
{
\Cli::write('- creating group: '.$config['name'], 'light_green');
list($group_id, $rows_affected) = \DB::insert(static::$data['ormauth_table'].'_groups')->set(array('name' => $config['name']))->execute();
}
// update the user group entries
\DB::update(static::$data['ormauth_table'])->set(array('group_id' => $group_id))->where('group_id', '=', $group)->execute();
// fetch the group as an ORM object, and assign the defined roles to it
$group = \Model\Auth_Group::find($group_id);
if ($group)
{
foreach ($config['roles'] as $role)
{
$role = \Model\Auth_Role::query()->where('name', '=', $role)->get_one();
if ( ! $role)
{
$role = \Model\Auth_Role::forge(array('name' => $role));
\Cli::write('- creating role: '.$role, 'light_green');
}
$group->roles[] = $role;
}
// update the group and save the roles
$group->save();
}
}
return true;
}
/*
* Deal with potential changes in users table layout between simpleauth and ormauth
*/
protected static function usertable()
{
if ( ! \DBUtil::table_exists(static::$data['ormauth_table']))
{
if ( ! \DBUtil::table_exists(static::$data['simpleauth_table']))
{
// table users
\DBUtil::create_table(static::$data['ormauth_table'], array(
'id' => array('type' => 'int', 'constraint' => 11, 'auto_increment' => true),
'username' => array('type' => 'varchar', 'constraint' => 50),
'password' => array('type' => 'varchar', 'constraint' => 255),
'group_id' => array('type' => 'int', 'constraint' => 11, 'default' => 1),
'email' => array('type' => 'varchar', 'constraint' => 255),
'last_login' => array('type' => 'varchar', 'constraint' => 25),
'previous_login' => array('type' => 'varchar', 'constraint' => 25, 'default' => 0),
'login_hash' => array('type' => 'varchar', 'constraint' => 255),
'user_id' => array('type' => 'int', 'constraint' => 11, 'default' => 0),
'created_at' => array('type' => 'int', 'constraint' => 11, 'default' => 0),
'updated_at' => array('type' => 'int', 'constraint' => 11, 'default' => 0),
), array('id'));
// add a unique index on username and email
\DBUtil::create_index(static::$data['ormauth_table'], array('username', 'email'), 'username', 'UNIQUE');
}
else
{
\DBUtil::rename_table(static::$data['simpleauth_table'], static::$data['ormauth_table']);
}
}
// run a check on required fields, and deal with missing ones. we might be migrating from simpleauth
if (\DBUtil::field_exists(static::$data['ormauth_table'], 'group'))
{
\DBUtil::modify_fields(static::$data['ormauth_table'], array(
'group' => array('name' => 'group_id', 'type' => 'int', 'constraint' => 11),
));
}
if ( ! \DBUtil::field_exists(static::$data['ormauth_table'], 'group_id'))
{
\DBUtil::add_fields(static::$data['ormauth_table'], array(
'group_id' => array('type' => 'int', 'constraint' => 11, 'default' => 1, 'after' => 'password'),
));
}
if ( ! \DBUtil::field_exists(static::$data['ormauth_table'], 'previous_login'))
{
\DBUtil::add_fields(static::$data['ormauth_table'], array(
'previous_login' => array('type' => 'varchar', 'constraint' => 25, 'default' => 0, 'after' => 'last_login'),
));
}
if ( ! \DBUtil::field_exists(static::$data['ormauth_table'], 'user_id'))
{
\DBUtil::add_fields(static::$data['ormauth_table'], array(
'user_id' => array('type' => 'int', 'constraint' => 11, 'default' => 0, 'after' => 'login_hash'),
));
}
if (\DBUtil::field_exists(static::$data['ormauth_table'], 'created'))
{
\DBUtil::modify_fields(static::$data['ormauth_table'], array(
'created' => array('name' => 'created_at', 'type' => 'int', 'constraint' => 11),
));
}
if ( ! \DBUtil::field_exists(static::$data['ormauth_table'], 'created_at'))
{
\DBUtil::add_fields(static::$data['ormauth_table'], array(
'created_at' => array('type' => 'int', 'constraint' => 11, 'default' => 0, 'after' => 'user_id'),
));
}
if (\DBUtil::field_exists(static::$data['ormauth_table'], 'updated'))
{
\DBUtil::modify_fields(static::$data['ormauth_table'], array(
'updated' => array('name' => 'updated_at', 'type' => 'int', 'constraint' => 11),
));
}
if ( ! \DBUtil::field_exists(static::$data['ormauth_table'], 'updated_at'))
{
\DBUtil::add_fields(static::$data['ormauth_table'], array(
'updated_at' => array('type' => 'int', 'constraint' => 11, 'default' => 0, 'after' => 'created_at'),
));
}
}
}