LoginSignup
5
6

More than 5 years have passed since last update.

FuelPHP 1.7 のSimpleAuthのEmail必須及びユニークチェックを外す

Last updated at Posted at 2015-12-13

1. 前提

  1. FuelPHP 1.7
  2. SimpleAuthを利用
  3. ユーザ作成をSimpleAuth にまかせている。

2. どう実装しよう?

  1. authパッケージ内を直接編集
  2. authパッケージを拡張してカスタムクラスを利用

2.の方が後々楽そう。

3. そもそもなぜEmailの必須を外すのか?

理由はいろいろとあると思いますが、社内システムを作るにあたり、登録予定のユーザの中に社内メールの割当がないとか、特定ユーザ郡はメールアドレスをメーリスにして登録メールアドレスが重複してしまうとかでしょうか?

4. 用意するファイル。

正しいかどうかわからないのが悔やまれるところですが、下記に配置する。
packages¥customauth
ディレクトリ構造はこんな感じ
必要なファイルをauthパッケージからコピー

packages¥auth¥classes¥login¥simpleauth.php
packages¥auth¥bootstrap.php

コピー後のディレクトリ構造

- packages
    ┗ customauth
        ┗ classes
            ┗ auth
                ┗ login
                    simpleauth.php
            bootstrap.php

5. 中身を見てみよう。

コピーしたファイルを舐めていきます。

ユーザ作成メソッド

packages¥customauth¥classes¥login¥simpleauth.php内の・・・
この辺があやしい・・・というかまんまだ!

編集前


    /**
     * Create new user
     *
     * @param   string
     * @param   string
     * @param   string  must contain valid email address
     * @param   int     group id
     * @param   Array
     * @return  bool
     */
    public function create_user($username, $password, $email, $group = 1, Array $profile_fields = array())
    {
        $password = trim($password);
        $email = filter_var(trim($email), FILTER_VALIDATE_EMAIL);

        if (empty($username) or empty($password) or empty($email))
        {
            throw new \SimpleUserUpdateException('Username, password or email address is not given, or email address is invalid', 1);
        }

        $same_users = \DB::select_array(\Config::get('simpleauth.table_columns', array('*')))
            ->where('username', '=', $username)
            ->or_where('email', '=', $email)
            ->from(\Config::get('simpleauth.table_name'))
            ->execute(\Config::get('simpleauth.db_connection'));

        if ($same_users->count() > 0)
        {
            if (in_array(strtolower($email), array_map('strtolower', $same_users->current())))
            {
                throw new \SimpleUserUpdateException('Email address already exists', 2);
            }
            else
            {
                throw new \SimpleUserUpdateException('Username already exists', 3);
            }
        }

        $user = array(
            'username'        => (string) $username,
            'password'        => $this->hash_password((string) $password),
            'email'           => $email,
            'group'           => (int) $group,
            'profile_fields'  => serialize($profile_fields),
            'last_login'      => 0,
            'login_hash'      => '',
            'created_at'      => \Date::forge()->get_timestamp(),
        );
        $result = \DB::insert(\Config::get('simpleauth.table_name'))
            ->set($user)
            ->execute(\Config::get('simpleauth.db_connection'));

        return ($result[1] > 0) ? $result[0] : false;
    }


上記ソースを下記に改定。


    /**
     * Create new user
     *
     * @param   string
     * @param   string
     * @param   string
     * @param   int     group id
     * @param   Array
     * @return  bool
     */
    public function create_user($username, $password, $email = null, $group = 1, Array $profile_fields = array())
    {
        $password = trim($password);

        if(!empty($email))
        {
            $email = filter_var(trim($email), FILTER_VALIDATE_EMAIL);
            if(empty($email))
            {
                throw new \SimpleUserUpdateException('emailの形式が不正です。', 1);
            }
        }

        if (empty($username) or empty($password))
        {
            throw new \SimpleUserUpdateException('Username, password is not given, or email address is invalid', 1);
        }

        $same_users = \DB::select_array(\Config::get('simpleauth.table_columns', array('*')))
            ->where('username', '=', $username)
            ->from(\Config::get('simpleauth.table_name'))
            ->execute(\Config::get('simpleauth.db_connection'));

        if ($same_users->count() > 0)
        {
            throw new \SimpleUserUpdateException('Username already exists', 3);
        }

        $user = array(
            'username'        => (string) $username,
            'password'        => $this->hash_password((string) $password),
            'email'           => $email,
            'group'           => (int) $group,
            'profile_fields'  => serialize($profile_fields),
            'last_login'      => 0,
            'login_hash'      => '',
            'created_at'      => \Date::forge()->get_timestamp(),
        );
        $result = \DB::insert(\Config::get('simpleauth.table_name'))
            ->set($user)
            ->execute(\Config::get('simpleauth.db_connection'));

        return ($result[1] > 0) ? $result[0] : false;
    }


こんな感じ。

ログインチェック

ログイン時にユーザの存在チェックをするメソッドを発見したのでこれもemailのチェックを外しておく。

    /**
     * Check the user exists
     *
     * @return  bool
     */
    public function validate_user($username_or_email = '', $password = '')
    {
        $username_or_email = trim($username_or_email) ?: trim(\Input::post(\Config::get('simpleauth.username_post_key', 'username')));
        $password = trim($password) ?: trim(\Input::post(\Config::get('simpleauth.password_post_key', 'password')));

        if (empty($username_or_email) or empty($password))
        {
            return false;
        }

        $password = $this->hash_password($password);
        $user = \DB::select_array(\Config::get('simpleauth.table_columns', array('*')))
            ->where_open()
            ->where('username', '=', $username_or_email)
            ->or_where('email', '=', $username_or_email)
            ->where_close()
            ->where('password', '=', $password)
            ->from(\Config::get('simpleauth.table_name'))
            ->execute(\Config::get('simpleauth.db_connection'))->current();

        return $user ?: false;
    }

email周りをごっそり削除

    /**
     * Check the user exists
     *
     * @return  bool
     */
    public function validate_user($username = '', $password = '')
    {
        $username = trim($username) ?: trim(\Input::post(\Config::get('simpleauth.username_post_key', 'username')));
        $password = trim($password) ?: trim(\Input::post(\Config::get('simpleauth.password_post_key', 'password')));

        if (empty($username) or empty($password))
        {
            return false;
        }

        $password = $this->hash_password($password);
        $user = \DB::select_array(\Config::get('simpleauth.table_columns', array('*')))
            ->where_open()
            ->where('username', '=', $username)
            ->where_close()
            ->where('password', '=', $password)
            ->from(\Config::get('simpleauth.table_name'))
            ->execute(\Config::get('simpleauth.db_connection'))->current();

        return $user ?: false;
    }

ログインメソッド

重要じゃないけど変数名に違和感ができてしまうので修正しておく。

    /**
     * Login user
     *
     * @param   string
     * @param   string
     * @return  bool
     */
    public function login($username_or_email = '', $password = '')
    {
        if ( ! ($this->user = $this->validate_user($username_or_email, $password)))
        {
            $this->user = \Config::get('simpleauth.guest_login', true) ? static::$guest_login : false;
            \Session::delete('username');
            \Session::delete('login_hash');
            return false;
        }

        // register so Auth::logout() can find us
        Auth::_register_verified($this);

        \Session::set('username', $this->user['username']);
        \Session::set('login_hash', $this->create_login_hash());
        \Session::instance()->rotate();
        return true;
    }

    /**
     * Login user
     *
     * @param   string
     * @param   string
     * @return  bool
     */
    public function login($username = '', $password = '')
    {
        if ( ! ($this->user = $this->validate_user($username, $password)))
        {
            $this->user = \Config::get('simpleauth.guest_login', true) ? static::$guest_login : false;
            \Session::delete('username');
            \Session::delete('login_hash');
            return false;
        }

        // register so Auth::logout() can find us
        Auth::_register_verified($this);

        \Session::set('username', $this->user['username']);
        \Session::set('login_hash', $this->create_login_hash());
        \Session::instance()->rotate();
        return true;
    }

ユーザ情報更新メソッド

こいつもemailの重複チェックとかしてるので修正が必要。

    /**
     * Update a user's properties
     * Note: Username cannot be updated, to update password the old password must be passed as old_password
     *
     * @param   Array  properties to be updated including profile fields
     * @param   string
     * @return  bool
     */
    public function update_user($values, $username = null)
    {
        $username = $username ?: $this->user['username'];
        $current_values = \DB::select_array(\Config::get('simpleauth.table_columns', array('*')))
            ->where('username', '=', $username)
            ->from(\Config::get('simpleauth.table_name'))
            ->execute(\Config::get('simpleauth.db_connection'));

        if (empty($current_values))
        {
            throw new \SimpleUserUpdateException('Username not found', 4);
        }

        $update = array();
        if (array_key_exists('username', $values))
        {
            throw new \SimpleUserUpdateException('Username cannot be changed.', 5);
        }
        if (array_key_exists('password', $values))
        {
            if (empty($values['old_password'])
                or $current_values->get('password') != $this->hash_password(trim($values['old_password'])))
            {
                throw new \SimpleUserWrongPassword('Old password is invalid');
            }

            $password = trim(strval($values['password']));
            if ($password === '')
            {
                throw new \SimpleUserUpdateException('Password can\'t be empty.', 6);
            }
            $update['password'] = $this->hash_password($password);
            unset($values['password']);
        }
        if (array_key_exists('old_password', $values))
        {
            unset($values['old_password']);
        }
        if (array_key_exists('email', $values))
        {
            $email = filter_var(trim($values['email']), FILTER_VALIDATE_EMAIL);
            if ( ! $email)
            {
                throw new \SimpleUserUpdateException('Email address is not valid', 7);
            }
            $matches = \DB::select()
                ->where('email', '=', $email)
                ->where('id', '!=', $current_values[0]['id'])
                ->from(\Config::get('simpleauth.table_name'))
                ->execute(\Config::get('simpleauth.db_connection'));
            if (count($matches))
            {
                throw new \SimpleUserUpdateException('Email address is already in use', 11);
            }
            $update['email'] = $email;
            unset($values['email']);
        }
        if (array_key_exists('group', $values))
        {
            if (is_numeric($values['group']))
            {
                $update['group'] = (int) $values['group'];
            }
            unset($values['group']);
        }
        if ( ! empty($values))
        {
            $profile_fields = @unserialize($current_values->get('profile_fields')) ?: array();
            foreach ($values as $key => $val)
            {
                if ($val === null)
                {
                    unset($profile_fields[$key]);
                }
                else
                {
                    $profile_fields[$key] = $val;
                }
            }
            $update['profile_fields'] = serialize($profile_fields);
        }

        $update['updated_at'] = \Date::forge()->get_timestamp();

        $affected_rows = \DB::update(\Config::get('simpleauth.table_name'))
            ->set($update)
            ->where('username', '=', $username)
            ->execute(\Config::get('simpleauth.db_connection'));

        // Refresh user
        if ($this->user['username'] == $username)
        {
            $this->user = \DB::select_array(\Config::get('simpleauth.table_columns', array('*')))
                ->where('username', '=', $username)
                ->from(\Config::get('simpleauth.table_name'))
                ->execute(\Config::get('simpleauth.db_connection'))->current();
        }

        return $affected_rows > 0;
    }

    /**
     * Update a user's properties
     * Note: Username cannot be updated, to update password the old password must be passed as old_password
     *
     * @param   Array  properties to be updated including profile fields
     * @param   string
     * @return  bool
     */
    public function update_user($values, $username = null)
    {
        $username = $username ?: $this->user['username'];
        $current_values = \DB::select_array(\Config::get('simpleauth.table_columns', array('*')))
            ->where('username', '=', $username)
            ->from(\Config::get('simpleauth.table_name'))
            ->execute(\Config::get('simpleauth.db_connection'));

        if (empty($current_values))
        {
            throw new \SimpleUserUpdateException('Username not found', 4);
        }

        $update = array();
        if (array_key_exists('username', $values))
        {
            throw new \SimpleUserUpdateException('Username cannot be changed.', 5);
        }
        if (array_key_exists('password', $values))
        {
            if (empty($values['old_password'])
                or $current_values->get('password') != $this->hash_password(trim($values['old_password'])))
            {
                throw new \SimpleUserWrongPassword('Old password is invalid');
            }

            $password = trim(strval($values['password']));
            if ($password === '')
            {
                throw new \SimpleUserUpdateException('Password can\'t be empty.', 6);
            }
            $update['password'] = $this->hash_password($password);
            unset($values['password']);
        }
        if (array_key_exists('old_password', $values))
        {
            unset($values['old_password']);
        }
        if (array_key_exists('email', $values))
        {
            $email = filter_var(trim($values['email']), FILTER_VALIDATE_EMAIL);
            if ( ! $email)
            {
                throw new \SimpleUserUpdateException('Email address is not valid', 7);
            }
            $update['email'] = $email;
            unset($values['email']);
        }
        if (array_key_exists('group', $values))
        {
            if (is_numeric($values['group']))
            {
                $update['group'] = (int) $values['group'];
            }
            unset($values['group']);
        }
        if ( ! empty($values))
        {
            $profile_fields = @unserialize($current_values->get('profile_fields')) ?: array();
            foreach ($values as $key => $val)
            {
                if ($val === null)
                {
                    unset($profile_fields[$key]);
                }
                else
                {
                    $profile_fields[$key] = $val;
                }
            }
            $update['profile_fields'] = serialize($profile_fields);
        }

        $update['updated_at'] = \Date::forge()->get_timestamp();

        $affected_rows = \DB::update(\Config::get('simpleauth.table_name'))
            ->set($update)
            ->where('username', '=', $username)
            ->execute(\Config::get('simpleauth.db_connection'));

        // Refresh user
        if ($this->user['username'] == $username)
        {
            $this->user = \DB::select_array(\Config::get('simpleauth.table_columns', array('*')))
                ->where('username', '=', $username)
                ->from(\Config::get('simpleauth.table_name'))
                ->execute(\Config::get('simpleauth.db_connection'))->current();
        }

        return $affected_rows > 0;
    }

namespaceの決定

namespace Auth;
namespace CustomAuth;

class の継承元変更

class Auth_Login_Simpleauth extends \Auth_Login_Driver
class Auth_Login_Simpleauth extends \Auth\Auth_Login_Simpleauth

bootstrap.phpの修正

下記ファイルを修正する。
packages¥auth¥bootstrap.php

<?php
/**
 * Fuel
 *
 * Fuel is a fast, lightweight, community driven PHP5 framework.
 *
 * @package    Fuel
 * @version    1.7
 * @author     Fuel Development Team
 * @license    MIT License
 * @copyright  2010 - 2015 Fuel Development Team
 * @link       http://fuelphp.com
 */

\Autoloader::add_core_namespace('Auth');

\Autoloader::add_classes(array(
    'Auth\\Auth'                        => __DIR__.'/classes/auth.php',
    'Auth\\AuthException'               => __DIR__.'/classes/auth.php',

    'Auth\\Auth_Driver'                 => __DIR__.'/classes/auth/driver.php',

    'Auth\\Auth_Opauth'                 => __DIR__.'/classes/auth/opauth.php',

    'Auth\\Auth_Acl_Driver'             => __DIR__.'/classes/auth/acl/driver.php',
    'Auth\\Auth_Acl_Simpleacl'          => __DIR__.'/classes/auth/acl/simpleacl.php',
    'Auth\\Auth_Acl_Ormacl'             => __DIR__.'/classes/auth/acl/ormacl.php',

    'Auth\\Auth_Group_Driver'           => __DIR__.'/classes/auth/group/driver.php',
    'Auth\\Auth_Group_Simplegroup'      => __DIR__.'/classes/auth/group/simplegroup.php',
    'Auth\\Auth_Group_Ormgroup'         => __DIR__.'/classes/auth/group/ormgroup.php',

    'Auth\\Auth_Login_Driver'           => __DIR__.'/classes/auth/login/driver.php',
    'Auth\\Auth_Login_Simpleauth'       => __DIR__.'/classes/auth/login/simpleauth.php',
    'Auth\\Auth_Login_Ormauth'          => __DIR__.'/classes/auth/login/ormauth.php',

    'Auth\\SimpleUserUpdateException'   => __DIR__.'/classes/auth/exceptions.php',
    'Auth\\SimpleUserWrongPassword'     => __DIR__.'/classes/auth/exceptions.php',
    'Auth\\OpauthException'             => __DIR__.'/classes/auth/exceptions.php',

    'Auth\\Model\\Auth_User'            => __DIR__.'/classes/model/auth/user.php',
    'Auth\\Model\\Auth_Userpermission'  => __DIR__.'/classes/model/auth/userpermission.php',
    'Auth\\Model\\Auth_Metadata'        => __DIR__.'/classes/model/auth/metadata.php',
    'Auth\\Model\\Auth_Group'           => __DIR__.'/classes/model/auth/group.php',
    'Auth\\Model\\Auth_Grouppermission' => __DIR__.'/classes/model/auth/grouppermission.php',
    'Auth\\Model\\Auth_Role'            => __DIR__.'/classes/model/auth/role.php',
    'Auth\\Model\\Auth_Rolepermission'  => __DIR__.'/classes/model/auth/rolepermission.php',
    'Auth\\Model\\Auth_Permission'      => __DIR__.'/classes/model/auth/permission.php',
    'Auth\\Model\\Auth_Provider'        => __DIR__.'/classes/model/auth/provider.php',
));

<?php

\Autoloader::add_core_namespace('CustomAuth');

\Autoloader::add_classes(array(
    'CustomAuth\\Auth_Login_Simpleauth'       => __DIR__.'/classes/auth/login/simpleauth.php',
));

結構いろいろ直したなぁ・・・

上記で動くようになると思います。

注意

上記修正は一貫してソース周りだけです。
migrationファイルでDB作成を行っている場合、emailにUK,NN制約が付いているので外してあげましょう。

GitHub Link

https://github.com/unagiya/FuelPHP_1_7_CustomAuth
https://github.com/bikun-bikun/FuelPHP_1_7_CustomAuth

2015-12-14追記

パッケージに追加したので、configから該当パッケージを読めるようにしないとダメでした。

config.phpから作成したパッケージを読み込めるように修正

修正するファイル
fuel\app\config\config.php

config.php修正前
        'packages'  => array(
            'auth',
            'parser',
            'orm',
            'less',
        ),

config.php修正後
        'packages'  => array(
            'auth',
            'parser',
            'orm',
            'less',
            'customauth',
        ),

5
6
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6