将一个createdBy字段添加到keystone.js中的用户模型中

我将“createdBy”字段添加到模型中,但是它允许pipe理员将所有用户选为“createdBy”用户。 我希望这个字段自动填充当前login的pipe理员,似乎无法使其工作。

理想情况下,这不会出现在用户界面中,而只是在用户保存时才被存储。

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' }] } }); 

虽然你的实现是function性的,但许多Keystone开发者(包括我自己)已经提出了关于通过POST发送user.id的安全风险的担忧。 当你说目前在Keystone中没有这样做的时候,你也是正确的。

我的解决scheme是在Keystone本身上实现该function。 我添加了一个可选的元模式,我称之为audit meta 。 这将两个字段添加到ListupdatedByupdatedBy ),我使用现有的req.usercaching副本填充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提交了一个pull请求( https://github.com/JedWatson/keystone/pull/490 ),其中包含了我的实现的详细说明。 所以,如果你急需这个东西,你总是可以拿出Keystone的副本,合并我的PR。

显然没有好办法做到这一点,但我确实想出了通过创build一个自定义的隐藏input字段来使用别人的想法。 这并不理想,但会为这个项目工作。 createdBy上的默认值就是这样,我可以使它成为一个必填字段,但是它被填充在表单中的模板,而不是他为那个inputtypes的初始模板。

 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' }] } }); 

那么自定义字段types就像这样,只是为表单和初始创build一个。 同时创buildfieldTypes / admin.js并更新fieldTypes.index.js

inputadmin / 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