Обеспечение доступа к коллекции со стороны клиента

У меня есть прототип метеорного приложения, который работает хорошо, но на данный момент очень небезопасно: мне нужно было отобразить список подходящих пользователей для текущего вошедшего в систему пользователя. Для начала я решил опубликовать всех пользователей, ограничив поля тем, что мне потребуется для фильтрации списка пользователей на стороне клиента.

Meteor.publish('users', function () {
  return Meteor.users.find({}, {
    fields: {
      'profile.picture': 1,
      'profile.likes': 1,
      'profile.friends': 1,
      'profile.type': 1
    }
  });
});

Затем в моем маршрутизаторе я бы сделал запрос, чтобы показать только то, что я хотел на стороне клиента:

Router.map(function() {
  this.route('usersList', {
    path: '/users',
    waitOn: function () {
      return Meteor.subscribe('users');
    },
    data: function () {
      var user = Meteor.user();
      return {
        users: Meteor.users.find({ $and: [
            {_id: {$ne : user._id}},
            {'profile.type': user.profile.interest}
          ]})
      };
    }
  });
});

В приведенном выше коде я опрашиваю всех пользователей, которые не являются текущим пользователем и тип которых соответствует интересам текущего пользователя. Я также отображаю определенную границу на фотографиях пользователей, у которых есть мой пользователь в их массиве "profile.friends", используя этот клиентский помощник:

Template.userItem.helpers({
  getClass: function(userId) {
    var user = Meteor.user();
    var lookedup = Meteor.users.findOne({_id: userId});
    if ($.inArray(user._id, lookedup.profile.friends) !== -1)
      return "yes";
    return "no";
  }
});

Теперь все это работает отлично, но при такой настройке каждый клиент может запрашивать у всех пользователей и получать их тип, изображение, список друзей и количество лайков. Если бы я был в MVC, эта информация была бы доступна только на стороне сервера. Поэтому я решил, что моя следующая итерация будет безопасна. Я бы переместил свой запрос из файла роутера в файл публикаций. Вот тут и начались неприятности ...

Meteor.publish('users', function () {
  var user = Meteor.users.findOne({_id: this.userId});
  var interest =  user.profile.interest;
  // retrieve all users, with their friends for now
  allUsers = Meteor.users.find({ $and: [
      {'_id': {$ne: user._id}},
      {'profile.type':interest}
    ]},
    { fields: {'profile.picture': 1, 'profile.friends': 1}}
  );
  return allUsers;
});

И в роутере:

Router.map(function() {
  this.route('usersList', {
    path: '/users',
    waitOn: function () {
      return Meteor.subscribe('users');
    },
    data: function () {
      var user = Meteor.user();
      return {users: Meteor.users.find({_id: {$ne : user._id}})};
    }
  });
});

(обратите внимание, что мне все еще нужно исключить текущего пользователя из запроса маршрутизатора, поскольку текущий пользователь всегда полностью публикуется)

Это работает,но:

список пользователей не обновляется, когда я изменяю интерес пользователя, а затем делаюRouter.go('usersList'), Только когда я обновляю браузер, мой список обновляется в соответствии с новыми интересами пользователя. Понятия не имею почему.это решение по-прежнему публикует друзей пользователей для отображения моих подходящих границ. Я хочу добавить временное поле в свой запрос на публикацию, установив для него значение «да», если пользователь находится в друзьях пользователя, и «нет» в противном случае, но ... пока что безуспешно.Я читал, я мог бы использовать агрегат, чтобы, возможно, достичь этого но до сих пор не удалось. Кроме того, агрегат не возвращает курсор, который ожидается от публикации.

Эта проблема заставляет меня усомниться в том, что метеорит подходит для безопасных приложений ... Этого было бы легко достичь в Rails или других!

РЕДАКТИРОВАТЬ: В соответствии с просьбой, вот код, который у меня есть до сих пор для передачи моей проверки "соответствия" на сервер:

Meteor.publish('users', function () {
  var user = Meteor.users.findOne({_id: this.userId});
  var interest =  user.profile.interest;
  // retrieve all users, with their friends for now
  allUsers = Meteor.users.find({ $and: [
      {'_id': {$ne: user._id}},
      {'profile.type':interest}
    ]},
    { fields: {'profile.picture': 1, 'profile.friends': 1}}
  );
  // ------------- ADDED ---------------
  allUsers.forEach(function (lookedup) {
    if (_.contains(lookedup.profile.friends, user._id))
      lookedup.profile.relation = "yes";
    else
        lookedup.profile.relation = "no";
    lookedup.profile.friends = undefined;
    return lookedup;
  });
  // ------------- END ---------------
  return allUsers;
});

Очевидно, что этот код не работает вообще, так как я не могу изменить значения курсора в цикле foreach. Но это дает представление о том, чего я хочу достичь: дать клиенту возможность узнать, подходит ли ему друг, или нет, не предоставляя клиенту доступ к спискам друзей всех пользователей. (а также избегая необходимости делать один запрос на каждого пользователя во время отображения, чтобы спросить сервер, соответствует ли этот конкретный пользователь этому конкретному)

Ответы на вопрос(1)

Ваш ответ на вопрос