【问题标题】:adding a createdBy field to the User model in keystone.js在 keystone.js 的 User 模型中添加 createdBy 字段
【发布时间】:2014-09-15 09:17:31
【问题描述】:

我将“createdBy”字段添加到模型中,但它允许管理员选择所有用户作为“createdBy”用户。我希望这个字段自动填充当前登录的管理员并且似乎无法让它工作。

理想情况下,这根本不会出现在 UI 中,而只是在保存用户时存储。

User.add({
    name: { type: Types.Name, required: true, index: true },
    email: { type: Types.Email, initial: true, required: true, index: true },
    company: { type: String, required: true, index: true, initial: true },
    phone: { type: String, required: true, index: true, initial: true },
    password: { type: Types.Password, initial: true, required: true },
    createdBy: { type: Types.Relationship, initial:true, required:true, ref: 'User' },
    createdAt: { type: Date, default: Date.now }
    }, 'Permissions', {
      level : { type: Types.Select, numeric: true, options: [{ value: 1, label: 'User'   }, {     value: 2, label: 'Group Administrator' }, { value: 3, label: 'System Administrator' }] }
    },
    'Screening', {
      rooms : { type: Types.Select, numeric: true, options: [{ value: 1, label: 'Screening room 1' }, { value: 2, label: 'Screening room 2' }, { value: 3, label: 'Screening room 3' }] }
});

【问题讨论】:

    标签: node.js mongoose keystonejs


    【解决方案1】:

    虽然您的实现功能正常,但许多 Keystone 开发人员(包括我自己)对通过 POST 发送 user.id 的安全风险提出了担忧。当您说目前在 Keystone 中没有这样做的好方法时,您也是正确的。

    我的解决方案是在 Keystone 本身上实现该功能。我添加了一个可选的元模式,我称之为audit meta。这将两个字段添加到ListcreatedByupdatedBy),我使用req.user 的现有缓存副本填充到UpdateHandler()。这样就不需要通过 POST 发送user._id

    要使用它,您只需在定义列表后添加List.addPattern('audit meta');,就像您使用standard meta 时一样。我对audit meta 的实现还添加了standard meta 字段,因此无需同时使用这两个字段。

    为了实现这一点,我对 Keystone 进行了以下更改

    首先,在lib\list.js 中,我在addPatern() 方法中添加了以下代码(以+ 为前缀):

    List.prototype.addPattern = function(pattern) {
    
        switch (pattern) {
            ...
    
    +       case 'audit meta':
    +           var userModel = keystone.get('user model');
    +
    +           if(!this.schema.path('createdOn') && !this.schema.path('updatedOn')) {
    +               this.addPattern('standard meta');
    +           }
    +
    +           if (userModel) {
    +               this.add({
    +                   createdBy: { type: Field.Types.Relationship, ref: userModel, hidden: true, index: true },
    +                   updatedBy: { type: Field.Types.Relationship, ref: userModel, hidden: true, index: true }
    +               });
    +               this.map('createdBy', 'createdBy');
    +               this.map('modifiedBy', 'updatedBy');
    +           }
    +       break;
    +
        }
    
        return this;
    

    然后在lib/updateHandler.js 中,我将以下代码添加到UpdateHandler.prototype.process(),就在方法结束时调用progress() 之前。

    +   // check for audit meta fields (mapped to createdBy/modifiedBy)
    +   if (this.list.mappings.createdBy && this.item.isNew) {
    +       this.item.set(this.list.mappings.createdBy, this.user._id);
    +   }
    +   if (this.list.mappings.modifiedBy) {
    +       this.item.set(this.list.mappings.modifiedBy, this.user._id);
    +   }
    

    之前我向 Keystone 提交了一个拉取请求 (https://github.com/JedWatson/keystone/pull/490),其中包括对我的实现的详细解释。所以,如果你迫切需要这个,你可以随时 fork 一份 Keystone 并合并我的 PR。

    【讨论】:

    • 酷,谢谢。我现在正在制作原型,但如果公司选择 keystone,我将进行此更新。
    • 不客气。希望我的 PR 将被合并,这将成为标准的 Keystone 功能。
    • 我提交了一个改进的 PR,#523,实现了一个 List track 选项,这是对现已撤销的 PR #490 的增强。
    • PR #523 现已合并。它将在下一次 KeystoneJS 更新中可用。
    【解决方案2】:

    显然没有很好的方法来做到这一点,但我确实想出了一个解决方法,通过创建自定义隐藏输入字段来使用其他人的想法。这并不理想,但适用于这个项目。 createdBy 的默认值只是为了让我可以将其设为必填字段,但它填充在表单中的翡翠模板中,而不是该输入类型的初始翡翠模板。

    User.add({
      name: { type: Types.Name, required: true, index: true },
      email: { type: Types.Email, initial: true, required: true, index: true },
      company: { type: String, required: true, index: true, initial: true },
      phone: { type: String, required: true, index: true, initial: true },
      password: { type: Types.Password, initial: true, required: true },
      createdBy: { type: Types.Admin, required: true, initial: true, default: 'createdBy' },
      createdAt: { type: Types.Hidden, default: Date.now }
    }, 'Permissions', {
      level : { type: Types.Select, numeric: true, options: [{ value: 1, label: 'User' }, {     value: 2, label: 'Group Administrator' }, { value: 3, label: 'System Administrator' }] }
    },Screening', {
      rooms : { type: Types.Select, numeric: true, options: [{ value: 1, label: 'Screening room 1' }, { value: 2, label: 'Screening room 2' }, { value: 3, label: 'Screening room 3' }] }
    });
    

    然后自定义字段类型就像这样,只需为表单和初始创建一个。同时创建 fieldTypes/admin.js 并更新 fieldTypes.index.js

    输入 admin/form.jade

    .field(class='type-' + field.type, data-field-type=field.type, data-field-path=field.path, data-field-collapse=field.collapse ? 'true' : false, data-field-depends-on=field.dependsOn, data-field-noedit=field.noedit ? 'true' : 'false')
    - var value = field.format(item)
    .field-ui(class='width-' + field.width)
        if field.noedit
            .field-value= user._id
        else
            input(type='hidden', name=field.path, value=user._id, autocomplete='off').form-control
        if field.note
            .field-note!= field.note
    

    【讨论】:

      猜你喜欢
      • 2014-09-28
      • 1970-01-01
      • 2015-05-16
      • 2017-04-30
      • 1970-01-01
      • 2020-04-20
      • 1970-01-01
      • 2015-04-10
      • 2013-05-06
      相关资源
      最近更新 更多