【问题标题】:How to honour user privacy settings in Meteor如何尊重 Meteor 中的用户隐私设置
【发布时间】:2015-01-27 15:18:04
【问题描述】:

我有一组这样定义的用户:

Accounts.createUser({
    username:'Simon', 
    email:'simon@email.com', 

    profile:{
        firstname:'Simon',
        lastname:'Surname',
        location:'Home Address',

        privacy: {
            location:0,
            emails:0 } //Location and emails are private and should not be disclosed
    }
});

我的问题是,在考虑个人资料隐私设置的情况下,如何发布此用户的记录供其他用户查看。在此示例中,我将位置和电子邮件的隐私设置为零,目的是不为该用户发布此信息。

我想使用标准方法发布它:

Meteor.publish("usersWithPublicEmails", function () {
    return Meteor.users.find();
});

但我看不到以仅发布公共信息的方式指定选择器或字段的方法。

我已尝试添加表单的其他出版物:

Meteor.publish("allUsers", function () {
    return Meteor.users.find( {}, {fields:{username:1}} );
});

Meteor.publish("usersWithPublicEmails", function () {
    return Meteor.users.find( {"profile.privacy.emails":1}, {fields:{username:1, emails:1}} );
});

但选择器似乎没有像我预期的那样返回电子邮件。从性能的角度来看,我正在寻找最佳方法。

【问题讨论】:

  • 嗯。我通过在我的 router.js 模块中添加一个缺少的订阅来完成这项工作。但是,在添加更多隐私设置(包括出版物和订阅)后,我看到了一些奇怪的行为。我的路由器中有 4 个订阅:waitOn: function(){ return Meteor.subscribe('allUsers') && Meteor.subscribe('usersWithPublicName') && Meteor.subscribe('usersWithPublicLocation') && Meteor.subscribe('usersWithPublicEmails') ; }, 我发现第 3 个订阅无效。更改顺序会从我的用户页面中删除相应的数据!
  • 我也尝试像这样waitOn: function(){ return [ Meteor.subscribe('allUsers'), Meteor.subscribe('usersWithPublicName'), Meteor.subscribe('usersWithPublicLocation'), Meteor.subscribe('usersWithPublicEmails') ] ; }, 指定我的waitOn,结果相同。

标签: meteor publish privacy


【解决方案1】:

Mongodb 不是关系数据库,所以每当我想基于元数据加入或查询时,我记得我必须以不同的方式做事。在您的情况下,如果我想查询用户隐私,我会为用户隐私制作一个单独的集合。此外,如果我关心性能,我可能永远不会想要“所有 x”,我只想向用户展示足够多的东西,从而分页。考虑到这两个想法,您可以轻松获得所需的内容:基于隐私设置和性能的查询。

Privacy = new Mongo.Collection("privacy");

每当我们想为帐户添加隐私时:

Privacy.insert({
  emails: 1,
  userId: account._id,
});

然后,一次一页,每页显示十个结果,用currentPage跟踪:

Meteor.publish("usersWithPublicEmails function (currentPage) {
    var results = []
    var privacyResults = Privacy.find({"emails":1}, {skip: currentPage,  
        limit: 10});
    var result;
    while (privacyResults.hasNext() ) {
       result = privacyResult.next();
       results.append(Meteor.users.find({_id: result.userId});
    }
    return result;
});

我没有测试这段代码,它可能有错误,但它应该给你一个大致的想法。这里的缺点是您必须使隐私和用户保持同步,但是当您不使用关系数据库时会遇到这些问题。

Mongodb 有一种方法可以用更少的代码进行这种引用查找,但它仍然按需进行,我更喜欢自己做的灵活性。如果你有兴趣看看Database references

【讨论】:

  • 嗨 Bjorn,我已经找到了我的案例中出了什么问题(缺少订阅),但这个建议非常有用。我一直想知道如何限制返回值,这个例子真的很有帮助。非常感谢。
  • Braunius,您在 StackOverflow 上点赞表示感谢。 ;\
  • 比约恩,我试过了,但我没有足够的声誉——这看起来很奇怪,但你去吧。顺便说一句,我发现您需要使用 privacyResults.forEach 来循环游标。在返回之前,我找不到一种方法来操纵记录集中的值——这对于我的场景来说是理想的。
【解决方案2】:

这是因为您在发布函数的 fields 对象中有错字,而不是 email 您输入了 emails

所以正确的函数应该是:

Meteor.publish("usersWithPublicEmails", function () {
    return Meteor.users.find( {"profile.privacy.emails":1}, {fields:{username:1, email:1}} );
});

此外,您已经在您的 allUsers 出版物中发布了所有用户名,因此,为了添加相关public 用户的缺失数据,您只需要这样:

Meteor.publish("usersWithPublicEmails", function () {
    return Meteor.users.find( {"profile.privacy.emails":1}, {fields:{email:1}} );
});

Meteor 会自动为您合并这些记录。

【讨论】:

  • 嗨,Serkan,这不是错字。 Meteor 帐户允许您使用 createUser 方法创建电子邮件,但会针对每个用户存储多封电子邮件。正如你所说,我期待流星合并记录,我很惊讶这没有发生。我一定做错了什么。感谢您花时间查看我的问题。
  • 嗨,Serkan,我已经找到了。我在路由器的 waitOn 子句中缺少匹配的订阅。 :-(
【解决方案3】:

最后一个简单的解决方案。我错过了路由器中的额外订阅:

Router.route('/users', {

    name: 'userList',

    waitOn: function(){
        return Meteor.subscribe('allUsers') &&
               Meteor.subscribe('usersWithPublicEmails');
    },

    data: function(){
        return Meteor.users.find();
    }
});

一个基本的错误:-(

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-20
    相关资源
    最近更新 更多