基本身份验证并设置引用电子邮件地址的用户模型


BasicAuth and setting a User model which reference e-mail address

我刚刚掌握了闪亮的新ATK 4.2,它看起来非常好。但是,我在使用基本身份验证类时遇到了问题。我想使用用户模型扩展基本身份验证。但是,我的用户模型不包含"电子邮件"字段,而是引用包含电子邮件地址的人员模型。

数据库表结构如下:

"人员"表

  • ID:主键
  • 姓名:夏亚
  • room_number:整数
  • 电子邮件: 字符

用户表

  • ID:主键
  • person_id:人员表 (id) 的外键
  • 密码:字符

ATK4.2 类如下:

人物模型

class Model_Person extends Model_Table {
public $entity_code='person';
function init(){
    parent::init();
    $this->addField('name');
    $this->addField('roomnumber');
    $this->addField('email');
}
}

用户模型

"用户"表包含密码字段。

class Model_User extends Model_Table {
public $entity_code='user';
function init(){
    parent::init();
    $this->hasOne('Person');
}
}

用户身份验证类

class UserAuth extends BasicAuth {
function init() {
    parent::init();
    $this->setModel('Model_User', 'email', 'password');
    $this->getModel()->addField('password')->system(true);
    $this->usePasswordEncryption('sha256/salt');
}
}

"经理"页。

管理员管理 mySQL 数据库中的表。

class page_mgr extends Page {
function init() {
    parent::init();
    $tabs=$this->add('Tabs');
    $crud=$tabs->addTab('Users')->add('CRUD');
    $crud->setModel('User');
    if($crud->grid){
        // Add prompt using user model id field.
        $crud->grid->addColumn('prompt','set_password_prompt');
        if($_GET['set_password_prompt']){
            $auth = $this->add('UserAuth');
            // load User from DB using row ID.
            $model = $auth->getModel()->loadData($_GET['set_password_prompt']);
            $model->set('password', $_GET['value'])->debug()->update();
            $this->js()->univ()->successMessage('Changed password for '.$model->ref('person_id')->get('email'))
              ->execute();
        }
    }
}
}

当我尝试在 CRUD 中设置用户密码时,按"确定"后出现以下错误。

#
Error in AJAXec response: SyntaxError: invalid XML attribute value

基本异常

未加载模型字段

附加信息:

Raised by object: Object Model_User(testing_admin_mgr_userauth_model_user)
id: 1
field: email

可能的操作:

Debug this Model
/

var/www/html/testing/atk4/lib/BaseException.php:38

Stack trace:
/var/www/html/testing/atk4/lib/BaseException.php    :38     BaseException BaseException->collectBasicData(Null, 1, 0)
/var/www/html/testing/atk4/lib/AbstractObject.php   :292    BaseException   BaseException->__construct("Model field was not loaded") / : (testing_admin_mgr_userauth_model_user Model_User->exception("Model field was not loaded")
/var/www/html/testing/atk4/lib/Model/Table.php  :87     Loggercall_user_func_array(Array(2), Array(1))
/var/www/html/testing/atk4/lib/Model.php    :115    testing_admin_mgr_userauth_model_user   Model_User->exception("Model field was not loaded")
/var/www/html/testing/atk4/lib/Model.php    :184    testing_admin_mgr_userauth_model_user   Model_User->get("email")
/var/www/html/testing/atk4/lib/Auth/Basic.php   :123    testing_admin_mgr_userauth_model_user   Model_User->offsetGet("email") /: Logger{closure}(Object(Model_User))
/var/www/html/testing/atk4/lib/AbstractObject.php   :427 (loggercall_user_func_array(Object(Closure), Array(1))
/var/www/html/testing/atk4/lib/Model/Table.php  :531    testing_admin_mgr_userauth_model_user   Model_User->hook("beforeSave")
/var/www/html/testing/atk4/lib/Model/Table.php  :612    testing_admin_mgr_userauth_model_user   Model_User->save()
/var/www/html/testing/admin/page/mgr.php    :26     testing_admin_mgr_userauth_model_user   Model_User->update()
/var/www/html/testing/atk4/lib/AbstractObject.php   :189    testing_admin_mgr   page_mgr->init()
/var/www/html/testing/atk4/lib/ApiFrontend.php  :92     testing_admin   Admin->add("page_mgr", "mgr", "Content")
/var/www/html/testing/atk4/lib/ApiWeb.php   :332    testing_admin   Admin->layout_Content()
/var/www/html/testing/atk4/lib/ApiFrontend.php  :33     testing_admin   Admin->addLayout("Content")
/var/www/html/testing/atk4/lib/ApiWeb.php   :208    testing_admin   Admin->initLayout()
/var/www/html/testing/admin/index.php   :7  testing_admin   Admin->main()

是否可以告诉 BasicAuth 引用 Person 模型来获取电子邮件字段,或者我们可以在用户模型中以某种方式为电子邮件地址添加别名?

干杯

更新 1

谢谢詹查,

为了使 CRUD 为用户显示与以前相同的字段并正确更新密码,我进行了以下更改。

人物模型

和以前一样。

用户模型

"用户"表包含密码字段。

class Model_User extends Model_Table {
public $entity_code='user';
function init(){
    parent::init();
    $person = $this->join("person", "person_id");
    $person->addField('email')->system(true);
    // hasOne() links the referenced table so CRUD can use 'id' and 'name' for drop down menus, etc.
    $this->hasOne('Person');
}
}

用户身份验证类

和以前一样。

"经理"页。

管理员管理 mySQL 数据库中的表。

class page_mgr extends Page {
function init() {
    parent::init();
    $tabs=$this->add('Tabs');
    $crud=$tabs->addTab('Users')->add('CRUD');
    $crud->setModel('User');
    if($crud->grid){
        // Add prompt using user model id field.
        $crud->grid->addColumn('prompt','set_password_prompt');
        if($_GET['set_password_prompt']){
            $auth = $this->add('UserAuth');
            // load User from DB using row ID.
            $model = $auth->getModel()->loadData($_GET['set_password_prompt']);
            $model->set('password', $_GET['value'])->save();
            $this->js()->univ()->successMessage('Changed password for '.$model->get('email'))
              ->execute();
        }
    }
}
}

以上更改效果很好,我可以成功更新用户的密码。

然而。。。。因为用户和人员之间有一个join()。当我选择删除用户条目时,"人员"表中的相应人员也会被删除。来自 join() 文档:"查询将连接表,插入、更新和删除将应用于两个表",因此产生了意想不到的副作用。

更新 2

好的,我想我已经通过将 join() 移动到身份验证类来解决它。以便 BasicAuth 类可以访问"电子邮件"字段。而 CRUD 类看不到联接,并删除了用户模型中的联接条目。

用户模型

class Model_User extends Model_Table {
public $entity_code='user';
function init(){
    parent::init();
    $this->hasOne('Person');
}
}

用户身份验证类

class UserAuth extends BasicAuth {
function init() {
    parent::init();
    $this->setModel('Model_User', 'email', 'password');
    $this->getModel()->addField('password')->system(true);
    $person = $this->getModel()->join("person", "person_id");
    $person->addField('email')->system(true);
    $this->usePasswordEncryption('sha256/salt');
}
}
  1. 在您的用户模型中,您应该有以下内容 - 删除 hasOne,而是:

    $person = $this->join("Person.person_id", "id");
    $person->addField("电子邮件");

  2. 使用$model->load()而不是loadData();

  3. 使用$model->save()而不是update();
相关文章: