MeteorJS遗留项目checkOrderStatus方法客户端更新权限错误原因
问题
我有一个遗留Meteor项目,包含Order对象及以下两个方法:
updateOrderStatus: function(props) { ... return Orders.update( { _id: props.orderInternalId }, { $set: { statusHistory: statusHistory, status: props.status } } ); }, checkOrderStatus: function(props) { ... // the update function call on both client and server var updateStatus = function(order) { newStatus = ... Orders.update( { _id: order._id }, { $set: { status: newStatus } } ); }; if (Meteor.isClient) { // for client, must subscribe to the order and fulfill first, else will return Meteor.subscribe("orderByOrderId", { orderId: props.orderId }, function( err ) { if (err) return throwError(err); var order = Orders.findOne({ orderId: props.orderId }); updateStatus(order); }); } else { var order = Orders.findOne({ orderId: props.orderId }); updateStatus(order); } }
调用第一个方法updateOrderStatus时,函数在客户端和服务端各执行两次,无错误及异常;调用第二个方法checkOrderStatus时,服务端可正常更新订单,但客户端会抛出错误:
update failed: Access denied. No allow validators set on restricted collection for method 'update'.
该错误在生产环境已存在数月,且未影响功能。已知Order对象未配置allow/deny规则,为何仅第二个方法会在客户端触发该错误?
原因分析
执行上下文的权限校验逻辑不同
updateOrderStatus是标准的Meteor方法,符合Meteor方法的「乐观UI」执行机制:客户端先本地模拟执行,再等待服务端执行结果同步。Meteor方法内部的集合操作,无论在客户端还是服务端执行,都走方法级权限校验,不会触发客户端集合的allow/deny规则检查,所以即使没配置allow/deny也不会报错。checkOrderStatus的客户端逻辑中,updateStatus是在Meteor.subscribe的回调里直接调用Orders.update——这属于客户端直接发起的集合更新操作,并非在Meteor方法内部执行。这种场景下Meteor会强制检查集合的allow规则,由于未配置任何allow规则,自然抛出「Access denied」错误。
为什么不影响功能?
服务端的checkOrderStatus已经完成了订单状态的正确更新,客户端的本地更新失败只是模拟操作出错,最终会被服务端同步过来的正确数据覆盖,因此实际功能不受影响。
内容的提问来源于stack exchange,提问作者mkto
相关产品推荐
相关产品推荐

