Meteor - Publish/Subscribe to user data while not logged in

Refresh

March 2019

Views

827 time

1

I've searched and read through pretty much all the questions relating to Meteor's pub/sub functionality but cant seem to find an answer that directly addresses my question.

I am learning Meteor and would like to create the following;

A user visits a page and is presented with an input box, they enter their username and if its a valid username I present them with the password input field.

The problem I seem to be having is that I cant access the Meteor.users collection unless I am logged in (the auto-publish and insecure packages have been removed).

So my question is 2 fold;

Is is possible to access the Meteor.users.find({username: 'value of input box'}) without being logged in?

If so, what do I need to do?

Here is how I have my code structured below;

/server/publications.js:

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

/lib/router.js:

Router.configure({
  layoutTemplate: 'layout'
});


Router.map(function() {
  this.route('home', {path: '/', data: function() {return Meteor.subscribe('staff');} });
});

/client/views/home/home.js:

Template.home.events({
  'submit form': function(e) {
  e.preventDefault();
  var guest = $("input#name");
  var staffMember = Meteor.users.findOne({username: $(guest).val()});
});

Unless I am logged in as any user, Meteor.users.find().fetch() always returns an empty array. Any help is greatly appreciated.

2 answers

1

You're publishing all your user data to everyone, now you just need to subscibe to it:

Deps.autorun(function(){
  Meteor.subscribe('staff');
});

That said, make sure that in such subscription you publish only non-sensitive user data, as it will be visible to everyone. Ideally, create another subscription for that purpose and filter just the username via the fields param.

1

You are publishing all the Users to be visible on the client. That is not a very secure position to be in since all your user data will be visible on all the clients. The pragmatic way to solve the problem is to allow the user to see only a limited number of users, i.e. publish a different set of users, depending on the userId.

As @Hubert's answer below indicates, you also need to subscribe to the publication on the client to actually fetch the published accounts over.


You can do this checking for validity securely by creating a Method call on the server:

/server/methods.js:

Meteor.method({
    validUserName: function (userName) {
        check(userName, string);
        // You have access to Meteor.users here.
        // This assumes that mere existence of a user with the same username will
        // render the entered username invalid. If there are more checks you want to
        // make, they should be made here.
        return !!Meteor.users.find({username: userName});
    }
});

/client/views/home/home.js:

Template.home.events({
  'submit form': function(e) {
  e.preventDefault();
  var guest = $("input#name");
  var userNameEntered = $(guest).val();

  Session.set('requestInProgress', true);

  Meteor.call('validUserName', function (isUserNameValid) {
       Session.set('requestInProgress', false);
       // ... take action here.
  });
});